github.com/matrixorigin/matrixone@v0.7.0/pkg/frontend/session.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  	"fmt"
    21  	"runtime"
    22  	"strings"
    23  	"sync"
    24  	"time"
    25  
    26  	"github.com/google/uuid"
    27  	"github.com/matrixorigin/matrixone/pkg/catalog"
    28  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    29  	"github.com/matrixorigin/matrixone/pkg/common/mpool"
    30  	moruntime "github.com/matrixorigin/matrixone/pkg/common/runtime"
    31  	"github.com/matrixorigin/matrixone/pkg/config"
    32  	"github.com/matrixorigin/matrixone/pkg/container/batch"
    33  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    34  	"github.com/matrixorigin/matrixone/pkg/defines"
    35  	"github.com/matrixorigin/matrixone/pkg/logutil"
    36  	"github.com/matrixorigin/matrixone/pkg/objectio"
    37  	logservicepb "github.com/matrixorigin/matrixone/pkg/pb/logservice"
    38  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    39  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
    40  	plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan"
    41  	"github.com/matrixorigin/matrixone/pkg/sql/util"
    42  	"github.com/matrixorigin/matrixone/pkg/txn/client"
    43  	"github.com/matrixorigin/matrixone/pkg/txn/clock"
    44  	"github.com/matrixorigin/matrixone/pkg/txn/storage/memorystorage"
    45  	"github.com/matrixorigin/matrixone/pkg/util/errutil"
    46  	"github.com/matrixorigin/matrixone/pkg/util/metric"
    47  	"github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace"
    48  	"github.com/matrixorigin/matrixone/pkg/vm/engine"
    49  	"github.com/matrixorigin/matrixone/pkg/vm/engine/memoryengine"
    50  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/moengine"
    51  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    52  )
    53  
    54  const MaxPrepareNumberInOneSession = 64
    55  
    56  // TODO: this variable should be configure by set variable
    57  const MoDefaultErrorCount = 64
    58  
    59  type ShowStatementType int
    60  
    61  const (
    62  	NotShowStatement ShowStatementType = 0
    63  	ShowColumns      ShowStatementType = 1
    64  	ShowTableStatus  ShowStatementType = 2
    65  )
    66  
    67  type TxnHandler struct {
    68  	storage   engine.Engine
    69  	txnClient TxnClient
    70  	ses       *Session
    71  	txn       TxnOperator
    72  	mu        sync.Mutex
    73  	entryMu   sync.Mutex
    74  }
    75  
    76  func InitTxnHandler(storage engine.Engine, txnClient TxnClient) *TxnHandler {
    77  	h := &TxnHandler{
    78  		storage:   &engine.EntireEngine{Engine: storage},
    79  		txnClient: txnClient,
    80  	}
    81  	return h
    82  }
    83  
    84  // we don't need to lock. TxnHandler is holded by one session.
    85  func (th *TxnHandler) SetTempEngine(te engine.Engine) {
    86  	ee := th.storage.(*engine.EntireEngine)
    87  	ee.TempEngine = te
    88  }
    89  
    90  type profileType uint8
    91  
    92  const (
    93  	profileTypeAccountWithName  profileType = 1 << 0
    94  	profileTypeAccountWithId                = 1 << 1
    95  	profileTypeSessionId                    = 1 << 2
    96  	profileTypeConnectionWithId             = 1 << 3
    97  	profileTypeConnectionWithIp             = 1 << 4
    98  
    99  	profileTypeAll = profileTypeAccountWithName | profileTypeAccountWithId |
   100  		profileTypeSessionId | profileTypeConnectionWithId | profileTypeConnectionWithIp
   101  
   102  	profileTypeConcise = profileTypeConnectionWithId
   103  )
   104  
   105  type Session struct {
   106  	// account id
   107  	accountId uint32
   108  
   109  	//protocol layer
   110  	protocol Protocol
   111  
   112  	//cmd from the client
   113  	cmd CommandType
   114  
   115  	//for test
   116  	mrs *MysqlResultSet
   117  
   118  	// mpool
   119  	mp *mpool.MPool
   120  
   121  	pu *config.ParameterUnit
   122  
   123  	isInternal bool
   124  
   125  	data         [][]interface{}
   126  	ep           *ExportParam
   127  	showStmtType ShowStatementType
   128  
   129  	txnHandler    *TxnHandler
   130  	txnCompileCtx *TxnCompilerContext
   131  	storage       engine.Engine
   132  	sql           string
   133  
   134  	sysVars         map[string]interface{}
   135  	userDefinedVars map[string]interface{}
   136  	gSysVars        *GlobalSystemVariables
   137  
   138  	//the server status
   139  	serverStatus uint16
   140  
   141  	//the option bits
   142  	optionBits uint32
   143  
   144  	prepareStmts map[string]*PrepareStmt
   145  	lastStmtId   uint32
   146  
   147  	requestCtx context.Context
   148  
   149  	//it gets the result set from the pipeline and send it to the client
   150  	outputCallback func(interface{}, *batch.Batch) error
   151  
   152  	//all the result set of executing the sql in background task
   153  	allResultSet []*MysqlResultSet
   154  
   155  	tenant *TenantInfo
   156  
   157  	uuid uuid.UUID
   158  
   159  	timeZone *time.Location
   160  
   161  	priv *privilege
   162  
   163  	errInfo *errInfo
   164  
   165  	//fromRealUser distinguish the sql that the user inputs from the one
   166  	//that the internal or background program executes
   167  	fromRealUser bool
   168  
   169  	cache *privilegeCache
   170  
   171  	profiles [8]string
   172  
   173  	mu sync.Mutex
   174  
   175  	flag         bool
   176  	lastInsertID uint64
   177  
   178  	skipAuth bool
   179  
   180  	sqlSourceType string
   181  
   182  	InitTempEngine bool
   183  
   184  	tempTablestorage *memorystorage.Storage
   185  
   186  	isBackgroundSession bool
   187  
   188  	tStmt *motrace.StatementInfo
   189  
   190  	ast tree.Statement
   191  
   192  	rs *plan.ResultColDef
   193  
   194  	QueryId []string
   195  
   196  	blockIdx int
   197  
   198  	p *plan.Plan
   199  
   200  	limitResultSize float64 // MB
   201  
   202  	curResultSize float64 // MB
   203  
   204  	createdTime time.Time
   205  
   206  	expiredTime time.Time
   207  
   208  	planCache *planCache
   209  
   210  	autoIncrCaches defines.AutoIncrCaches
   211  }
   212  
   213  // The update version. Four function.
   214  func (ses *Session) SetAutoIncrCaches(autocaches defines.AutoIncrCaches) {
   215  	ses.mu.Lock()
   216  	defer ses.mu.Unlock()
   217  	ses.autoIncrCaches = autocaches
   218  }
   219  
   220  func (ses *Session) GetAutoIncrCaches() defines.AutoIncrCaches {
   221  	ses.mu.Lock()
   222  	defer ses.mu.Unlock()
   223  	return ses.autoIncrCaches
   224  }
   225  
   226  const saveQueryIdCnt = 10
   227  
   228  func (ses *Session) pushQueryId(uuid string) {
   229  	if len(ses.QueryId) > saveQueryIdCnt {
   230  		ses.QueryId = ses.QueryId[1:]
   231  	}
   232  	ses.QueryId = append(ses.QueryId, uuid)
   233  }
   234  
   235  // Clean up all resources hold by the session.  As of now, the mpool
   236  func (ses *Session) Dispose() {
   237  	if ses.flag {
   238  		mp := ses.GetMemPool()
   239  		mpool.DeleteMPool(mp)
   240  		ses.SetMemPool(mp)
   241  	}
   242  	ses.cleanCache()
   243  }
   244  
   245  type errInfo struct {
   246  	codes  []uint16
   247  	msgs   []string
   248  	maxCnt int
   249  }
   250  
   251  func (e *errInfo) push(code uint16, msg string) {
   252  	if e.maxCnt > 0 && len(e.codes) > e.maxCnt {
   253  		e.codes = e.codes[1:]
   254  		e.msgs = e.msgs[1:]
   255  	}
   256  	e.codes = append(e.codes, code)
   257  	e.msgs = append(e.msgs, msg)
   258  }
   259  
   260  func (e *errInfo) length() int {
   261  	return len(e.codes)
   262  }
   263  
   264  func NewSession(proto Protocol, mp *mpool.MPool, pu *config.ParameterUnit, gSysVars *GlobalSystemVariables, flag bool) *Session {
   265  	txnHandler := InitTxnHandler(pu.StorageEngine, pu.TxnClient)
   266  	ses := &Session{
   267  		protocol: proto,
   268  		mp:       mp,
   269  		pu:       pu,
   270  		ep: &ExportParam{
   271  			ExportParam: &tree.ExportParam{
   272  				Outfile: false,
   273  				Fields:  &tree.Fields{},
   274  				Lines:   &tree.Lines{},
   275  			},
   276  		},
   277  		txnHandler: txnHandler,
   278  		//TODO:fix database name after the catalog is ready
   279  		txnCompileCtx: InitTxnCompilerContext(txnHandler, proto.GetDatabaseName()),
   280  		storage:       &engine.EntireEngine{Engine: pu.StorageEngine},
   281  		gSysVars:      gSysVars,
   282  
   283  		serverStatus: 0,
   284  		optionBits:   0,
   285  
   286  		outputCallback: getDataFromPipeline,
   287  		timeZone:       time.Local,
   288  		errInfo: &errInfo{
   289  			codes:  make([]uint16, 0, MoDefaultErrorCount),
   290  			msgs:   make([]string, 0, MoDefaultErrorCount),
   291  			maxCnt: MoDefaultErrorCount,
   292  		},
   293  		cache:     &privilegeCache{},
   294  		blockIdx:  0,
   295  		planCache: newPlanCache(100),
   296  	}
   297  	if flag {
   298  		ses.sysVars = gSysVars.CopySysVarsToSession()
   299  		ses.userDefinedVars = make(map[string]interface{})
   300  		ses.prepareStmts = make(map[string]*PrepareStmt)
   301  	}
   302  	ses.flag = flag
   303  	ses.uuid, _ = uuid.NewUUID()
   304  	ses.SetOptionBits(OPTION_AUTOCOMMIT)
   305  	ses.GetTxnCompileCtx().SetSession(ses)
   306  	ses.GetTxnHandler().SetSession(ses)
   307  
   308  	var err error
   309  	if ses.mp == nil {
   310  		// If no mp, we create one for session.  Use GuestMmuLimitation as cap.
   311  		// fixed pool size can be another param, or should be computed from cap,
   312  		// but here, too lazy, just use Mid.
   313  		//
   314  		// XXX MPOOL
   315  		// We don't have a way to close a session, so the only sane way of creating
   316  		// a mpool is to use NoFixed
   317  		ses.mp, err = mpool.NewMPool("pipeline-"+ses.GetUUIDString(), pu.SV.GuestMmuLimitation, mpool.NoFixed)
   318  		if err != nil {
   319  			panic(err)
   320  		}
   321  	}
   322  
   323  	runtime.SetFinalizer(ses, func(ss *Session) {
   324  		ss.Dispose()
   325  	})
   326  	return ses
   327  }
   328  
   329  // BackgroundSession executing the sql in background
   330  type BackgroundSession struct {
   331  	*Session
   332  	cancel context.CancelFunc
   333  }
   334  
   335  // NewBackgroundSession generates an independent background session executing the sql
   336  func NewBackgroundSession(ctx context.Context, mp *mpool.MPool, PU *config.ParameterUnit, gSysVars *GlobalSystemVariables, autoincrcaches defines.AutoIncrCaches) *BackgroundSession {
   337  	ses := NewSession(&FakeProtocol{}, mp, PU, gSysVars, false)
   338  	ses.SetOutputCallback(fakeDataSetFetcher)
   339  	ses.SetAutoIncrCaches(autoincrcaches)
   340  	if stmt := motrace.StatementFromContext(ctx); stmt != nil {
   341  		logutil.Infof("session uuid: %s -> background session uuid: %s", uuid.UUID(stmt.SessionID).String(), ses.uuid.String())
   342  	}
   343  	cancelBackgroundCtx, cancelBackgroundFunc := context.WithCancel(ctx)
   344  	ses.SetRequestContext(cancelBackgroundCtx)
   345  	ses.SetBackgroundSession(true)
   346  	backSes := &BackgroundSession{
   347  		Session: ses,
   348  		cancel:  cancelBackgroundFunc,
   349  	}
   350  	return backSes
   351  }
   352  
   353  func (bgs *BackgroundSession) Close() {
   354  	if bgs.cancel != nil {
   355  		bgs.cancel()
   356  	}
   357  
   358  	if bgs.Session != nil {
   359  		bgs.Session.ep = nil
   360  		bgs.Session.errInfo.codes = nil
   361  		bgs.Session.errInfo.msgs = nil
   362  		bgs.Session.errInfo = nil
   363  		bgs.Session.cache.invalidate()
   364  		bgs.Session.cache = nil
   365  		bgs.Session.txnCompileCtx = nil
   366  		bgs.Session.txnHandler = nil
   367  		bgs.Session.gSysVars = nil
   368  	}
   369  	bgs = nil
   370  }
   371  
   372  func (ses *Session) GetIncBlockIdx() int {
   373  	ses.blockIdx++
   374  	return ses.blockIdx
   375  }
   376  
   377  func (ses *Session) ResetBlockIdx() {
   378  	ses.blockIdx = 0
   379  }
   380  
   381  func (ses *Session) SetBackgroundSession(b bool) {
   382  	ses.mu.Lock()
   383  	defer ses.mu.Unlock()
   384  	ses.isBackgroundSession = b
   385  }
   386  
   387  func (ses *Session) IsBackgroundSession() bool {
   388  	ses.mu.Lock()
   389  	defer ses.mu.Unlock()
   390  	return ses.isBackgroundSession
   391  }
   392  
   393  func (ses *Session) cachePlan(sql string, stmts []tree.Statement, plans []*plan.Plan) {
   394  	ses.mu.Lock()
   395  	defer ses.mu.Unlock()
   396  	ses.planCache.cache(sql, stmts, plans)
   397  }
   398  
   399  func (ses *Session) getCachedPlan(sql string) *cachedPlan {
   400  	ses.mu.Lock()
   401  	defer ses.mu.Unlock()
   402  	return ses.planCache.get(sql)
   403  }
   404  
   405  func (ses *Session) isCached(sql string) bool {
   406  	ses.mu.Lock()
   407  	defer ses.mu.Unlock()
   408  	return ses.planCache.isCached(sql)
   409  }
   410  
   411  func (ses *Session) cleanCache() {
   412  	ses.mu.Lock()
   413  	defer ses.mu.Unlock()
   414  	ses.planCache.clean()
   415  }
   416  
   417  func (ses *Session) setSkipCheckPrivilege(b bool) {
   418  	ses.mu.Lock()
   419  	defer ses.mu.Unlock()
   420  	ses.skipAuth = b
   421  }
   422  
   423  func (ses *Session) skipCheckPrivilege() bool {
   424  	ses.mu.Lock()
   425  	defer ses.mu.Unlock()
   426  	return ses.skipAuth
   427  }
   428  
   429  func (ses *Session) makeProfile(profileTyp profileType) {
   430  	ses.mu.Lock()
   431  	defer ses.mu.Unlock()
   432  	var mask profileType
   433  	var profile string
   434  	account := ses.tenant
   435  	for i := uint8(0); i < 8; i++ {
   436  		mask = 1 << i
   437  		switch mask & profileTyp {
   438  		case profileTypeAccountWithName:
   439  			if account != nil {
   440  				profile = fmt.Sprintf("account: %s user: %s role: %s", account.GetTenant(), account.GetUser(), account.GetDefaultRole())
   441  			}
   442  		case profileTypeAccountWithId:
   443  			if account != nil {
   444  				profile = fmt.Sprintf("accountId: %d userId: %d roleId: %d", account.GetTenantID(), account.GetUserID(), account.GetDefaultRoleID())
   445  			}
   446  		case profileTypeSessionId:
   447  			profile = "sessionId " + ses.uuid.String()
   448  		case profileTypeConnectionWithId:
   449  			if ses.protocol != nil {
   450  				profile = fmt.Sprintf("connectionId %d", ses.protocol.ConnectionID())
   451  			}
   452  		case profileTypeConnectionWithIp:
   453  			if ses.protocol != nil {
   454  				h, p, _, _ := ses.protocol.Peer()
   455  				profile = "client " + h + ":" + p
   456  			}
   457  		default:
   458  			profile = ""
   459  		}
   460  		ses.profiles[i] = profile
   461  	}
   462  }
   463  
   464  func (ses *Session) MakeProfile() {
   465  	ses.makeProfile(profileTypeAll)
   466  }
   467  
   468  func (ses *Session) getProfile(profileTyp profileType) string {
   469  	ses.mu.Lock()
   470  	defer ses.mu.Unlock()
   471  	var mask profileType
   472  	sb := bytes.Buffer{}
   473  	for i := uint8(0); i < 8; i++ {
   474  		mask = 1 << i
   475  		if mask&profileTyp != 0 {
   476  			if sb.Len() != 0 {
   477  				sb.WriteByte(' ')
   478  			}
   479  			sb.WriteString(ses.profiles[i])
   480  		}
   481  	}
   482  	return sb.String()
   483  }
   484  
   485  func (ses *Session) GetConciseProfile() string {
   486  	return ses.getProfile(profileTypeConcise)
   487  }
   488  
   489  func (ses *Session) GetCompleteProfile() string {
   490  	return ses.getProfile(profileTypeAll)
   491  }
   492  
   493  func (ses *Session) IfInitedTempEngine() bool {
   494  	ses.mu.Lock()
   495  	defer ses.mu.Unlock()
   496  	return ses.InitTempEngine
   497  }
   498  
   499  func (ses *Session) GetTempTableStorage() *memorystorage.Storage {
   500  	if ses.tempTablestorage == nil {
   501  		panic("temp table storage is not initialized")
   502  	}
   503  	return ses.tempTablestorage
   504  }
   505  
   506  func (ses *Session) SetTempTableStorage(ck clock.Clock) (*logservicepb.DNStore, error) {
   507  	// Without concurrency, there is no potential for data competition
   508  
   509  	// Arbitrary value is OK since it's single sharded. Let's use 0xbeef
   510  	// suggested by @reusee
   511  	shard := logservicepb.DNShardInfo{
   512  		ShardID:   0xbeef,
   513  		ReplicaID: 0xbeef,
   514  	}
   515  	shards := []logservicepb.DNShardInfo{
   516  		shard,
   517  	}
   518  	// Arbitrary value is OK, for more information about TEMPORARY_TABLE_DN_ADDR, please refer to the comment in defines/const.go
   519  	dnAddr := defines.TEMPORARY_TABLE_DN_ADDR
   520  	dnStore := logservicepb.DNStore{
   521  		UUID:           uuid.NewString(),
   522  		ServiceAddress: dnAddr,
   523  		Shards:         shards,
   524  	}
   525  
   526  	ms, err := memorystorage.NewMemoryStorage(
   527  		mpool.MustNewZero(),
   528  		ck,
   529  		memoryengine.RandomIDGenerator,
   530  	)
   531  	if err != nil {
   532  		return nil, err
   533  	}
   534  	ses.tempTablestorage = ms
   535  	return &dnStore, nil
   536  }
   537  
   538  func (ses *Session) GetPrivilegeCache() *privilegeCache {
   539  	ses.mu.Lock()
   540  	defer ses.mu.Unlock()
   541  	return ses.cache
   542  }
   543  
   544  func (ses *Session) InvalidatePrivilegeCache() {
   545  	ses.mu.Lock()
   546  	defer ses.mu.Unlock()
   547  	ses.cache.invalidate()
   548  }
   549  
   550  // GetBackgroundExec generates a background executor
   551  func (ses *Session) GetBackgroundExec(ctx context.Context) BackgroundExec {
   552  	return NewBackgroundHandler(ctx, ses.GetMemPool(), ses.GetParameterUnit(), ses.autoIncrCaches)
   553  }
   554  
   555  func (ses *Session) GetIsInternal() bool {
   556  	ses.mu.Lock()
   557  	defer ses.mu.Unlock()
   558  	return ses.isInternal
   559  }
   560  
   561  func (ses *Session) SetMemPool(mp *mpool.MPool) {
   562  	ses.mu.Lock()
   563  	defer ses.mu.Unlock()
   564  	ses.mp = mp
   565  }
   566  
   567  func (ses *Session) GetMemPool() *mpool.MPool {
   568  	ses.mu.Lock()
   569  	defer ses.mu.Unlock()
   570  	return ses.mp
   571  }
   572  
   573  func (ses *Session) GetParameterUnit() *config.ParameterUnit {
   574  	ses.mu.Lock()
   575  	defer ses.mu.Unlock()
   576  	return ses.pu
   577  }
   578  
   579  func (ses *Session) GetData() [][]interface{} {
   580  	ses.mu.Lock()
   581  	defer ses.mu.Unlock()
   582  	return ses.data
   583  }
   584  
   585  func (ses *Session) SetData(data [][]interface{}) {
   586  	ses.mu.Lock()
   587  	defer ses.mu.Unlock()
   588  	ses.data = data
   589  }
   590  
   591  func (ses *Session) AppendData(row []interface{}) {
   592  	ses.mu.Lock()
   593  	defer ses.mu.Unlock()
   594  	ses.data = append(ses.data, row)
   595  }
   596  
   597  func (ses *Session) SetExportParam(ep *tree.ExportParam) {
   598  	ses.mu.Lock()
   599  	defer ses.mu.Unlock()
   600  	ses.ep.ExportParam = ep
   601  }
   602  
   603  func (ses *Session) GetExportParam() *ExportParam {
   604  	ses.mu.Lock()
   605  	defer ses.mu.Unlock()
   606  	return ses.ep
   607  }
   608  
   609  func (ses *Session) SetShowStmtType(sst ShowStatementType) {
   610  	ses.mu.Lock()
   611  	defer ses.mu.Unlock()
   612  	ses.showStmtType = sst
   613  }
   614  
   615  func (ses *Session) GetShowStmtType() ShowStatementType {
   616  	ses.mu.Lock()
   617  	defer ses.mu.Unlock()
   618  	return ses.showStmtType
   619  }
   620  
   621  func (ses *Session) GetOutputCallback() func(interface{}, *batch.Batch) error {
   622  	ses.mu.Lock()
   623  	defer ses.mu.Unlock()
   624  	return ses.outputCallback
   625  }
   626  
   627  func (ses *Session) GetErrInfo() *errInfo {
   628  	ses.mu.Lock()
   629  	defer ses.mu.Unlock()
   630  	return ses.errInfo
   631  }
   632  
   633  func (ses *Session) GenNewStmtId() uint32 {
   634  	ses.mu.Lock()
   635  	defer ses.mu.Unlock()
   636  	ses.lastStmtId = ses.lastStmtId + 1
   637  	return ses.lastStmtId
   638  }
   639  
   640  func (ses *Session) GetLastStmtId() uint32 {
   641  	ses.mu.Lock()
   642  	defer ses.mu.Unlock()
   643  	return ses.lastStmtId
   644  }
   645  
   646  func (ses *Session) SetLastInsertID(num uint64) {
   647  	ses.mu.Lock()
   648  	defer ses.mu.Unlock()
   649  	ses.lastInsertID = num
   650  }
   651  
   652  func (ses *Session) GetLastInsertID() uint64 {
   653  	ses.mu.Lock()
   654  	defer ses.mu.Unlock()
   655  	return ses.lastInsertID
   656  }
   657  
   658  func (ses *Session) SetRequestContext(reqCtx context.Context) {
   659  	ses.mu.Lock()
   660  	defer ses.mu.Unlock()
   661  	ses.requestCtx = reqCtx
   662  }
   663  
   664  func (ses *Session) GetRequestContext() context.Context {
   665  	ses.mu.Lock()
   666  	defer ses.mu.Unlock()
   667  	return ses.requestCtx
   668  }
   669  
   670  func (ses *Session) SetTimeZone(loc *time.Location) {
   671  	ses.mu.Lock()
   672  	defer ses.mu.Unlock()
   673  	ses.timeZone = loc
   674  }
   675  
   676  func (ses *Session) GetTimeZone() *time.Location {
   677  	ses.mu.Lock()
   678  	defer ses.mu.Unlock()
   679  	return ses.timeZone
   680  }
   681  
   682  func (ses *Session) SetCmd(cmd CommandType) {
   683  	ses.mu.Lock()
   684  	defer ses.mu.Unlock()
   685  	ses.cmd = cmd
   686  }
   687  
   688  func (ses *Session) GetCmd() CommandType {
   689  	ses.mu.Lock()
   690  	defer ses.mu.Unlock()
   691  	return ses.cmd
   692  }
   693  
   694  func (ses *Session) SetMysqlResultSet(mrs *MysqlResultSet) {
   695  	ses.mu.Lock()
   696  	defer ses.mu.Unlock()
   697  	ses.mrs = mrs
   698  }
   699  
   700  func (ses *Session) GetMysqlResultSet() *MysqlResultSet {
   701  	ses.mu.Lock()
   702  	defer ses.mu.Unlock()
   703  	return ses.mrs
   704  }
   705  
   706  func (ses *Session) AppendMysqlResultSetOfBackgroundTask(mrs *MysqlResultSet) {
   707  	ses.mu.Lock()
   708  	defer ses.mu.Unlock()
   709  	ses.allResultSet = append(ses.allResultSet, mrs)
   710  }
   711  
   712  func (ses *Session) GetAllMysqlResultSet() []*MysqlResultSet {
   713  	ses.mu.Lock()
   714  	defer ses.mu.Unlock()
   715  	return ses.allResultSet
   716  }
   717  
   718  func (ses *Session) ClearAllMysqlResultSet() {
   719  	ses.mu.Lock()
   720  	defer ses.mu.Unlock()
   721  	if ses.allResultSet != nil {
   722  		ses.allResultSet = ses.allResultSet[:0]
   723  	}
   724  }
   725  
   726  func (ses *Session) GetTenantInfo() *TenantInfo {
   727  	ses.mu.Lock()
   728  	defer ses.mu.Unlock()
   729  	return ses.tenant
   730  }
   731  
   732  // GetTenantName return tenant name according to GetTenantInfo and stmt.
   733  //
   734  // With stmt = nil, should be only called in TxnHandler.NewTxn, TxnHandler.CommitTxn, TxnHandler.RollbackTxn
   735  func (ses *Session) GetTenantName(stmt tree.Statement) string {
   736  	tenant := sysAccountName
   737  	if ses.GetTenantInfo() != nil && (stmt == nil || !IsPrepareStatement(stmt)) {
   738  		tenant = ses.GetTenantInfo().GetTenant()
   739  	}
   740  	return tenant
   741  }
   742  
   743  func (ses *Session) GetUUID() []byte {
   744  	ses.mu.Lock()
   745  	defer ses.mu.Unlock()
   746  	return ses.uuid[:]
   747  }
   748  
   749  func (ses *Session) GetUUIDString() string {
   750  	ses.mu.Lock()
   751  	defer ses.mu.Unlock()
   752  	return ses.uuid.String()
   753  }
   754  
   755  func (ses *Session) SetTenantInfo(ti *TenantInfo) {
   756  	ses.mu.Lock()
   757  	defer ses.mu.Unlock()
   758  	ses.tenant = ti
   759  }
   760  
   761  func (ses *Session) SetPrepareStmt(name string, prepareStmt *PrepareStmt) error {
   762  	ses.mu.Lock()
   763  	defer ses.mu.Unlock()
   764  	if _, ok := ses.prepareStmts[name]; !ok {
   765  		if len(ses.prepareStmts) >= MaxPrepareNumberInOneSession {
   766  			return moerr.NewInvalidState(ses.requestCtx, "too many prepared statement, max %d", MaxPrepareNumberInOneSession)
   767  		}
   768  	}
   769  	ses.prepareStmts[name] = prepareStmt
   770  	return nil
   771  }
   772  
   773  func (ses *Session) GetPrepareStmt(name string) (*PrepareStmt, error) {
   774  	ses.mu.Lock()
   775  	defer ses.mu.Unlock()
   776  	if prepareStmt, ok := ses.prepareStmts[name]; ok {
   777  		return prepareStmt, nil
   778  	}
   779  	return nil, moerr.NewInvalidState(ses.requestCtx, "prepared statement '%s' does not exist", name)
   780  }
   781  
   782  func (ses *Session) RemovePrepareStmt(name string) {
   783  	ses.mu.Lock()
   784  	defer ses.mu.Unlock()
   785  	delete(ses.prepareStmts, name)
   786  }
   787  
   788  func (ses *Session) SetSysVar(name string, value interface{}) {
   789  	ses.mu.Lock()
   790  	defer ses.mu.Unlock()
   791  	ses.sysVars[name] = value
   792  }
   793  
   794  func (ses *Session) GetSysVar(name string) interface{} {
   795  	ses.mu.Lock()
   796  	defer ses.mu.Unlock()
   797  	return ses.sysVars[name]
   798  }
   799  
   800  func (ses *Session) GetSysVars() map[string]interface{} {
   801  	ses.mu.Lock()
   802  	defer ses.mu.Unlock()
   803  	return ses.sysVars
   804  }
   805  
   806  func (ses *Session) GetGlobalSysVars() *GlobalSystemVariables {
   807  	ses.mu.Lock()
   808  	defer ses.mu.Unlock()
   809  	return ses.gSysVars
   810  }
   811  
   812  // SetGlobalVar sets the value of system variable in global.
   813  // used by SET GLOBAL
   814  func (ses *Session) SetGlobalVar(name string, value interface{}) error {
   815  	return ses.GetGlobalSysVars().SetGlobalSysVar(ses.GetRequestContext(), name, value)
   816  }
   817  
   818  // GetGlobalVar gets this value of the system variable in global
   819  func (ses *Session) GetGlobalVar(name string) (interface{}, error) {
   820  	gSysVars := ses.GetGlobalSysVars()
   821  	if def, val, ok := gSysVars.GetGlobalSysVar(name); ok {
   822  		if def.GetScope() == ScopeSession {
   823  			//empty
   824  			return nil, moerr.NewInternalError(ses.GetRequestContext(), errorSystemVariableSessionEmpty())
   825  		}
   826  		return val, nil
   827  	}
   828  	return nil, moerr.NewInternalError(ses.GetRequestContext(), errorSystemVariableDoesNotExist())
   829  }
   830  
   831  func (ses *Session) GetTxnCompileCtx() *TxnCompilerContext {
   832  	ses.mu.Lock()
   833  	defer ses.mu.Unlock()
   834  	return ses.txnCompileCtx
   835  }
   836  
   837  // SetSessionVar sets the value of system variable in session
   838  func (ses *Session) SetSessionVar(name string, value interface{}) error {
   839  	gSysVars := ses.GetGlobalSysVars()
   840  	if def, _, ok := gSysVars.GetGlobalSysVar(name); ok {
   841  		if def.GetScope() == ScopeGlobal {
   842  			return moerr.NewInternalError(ses.GetRequestContext(), errorSystemVariableIsGlobal())
   843  		}
   844  		//scope session & both
   845  		if !def.GetDynamic() {
   846  			return moerr.NewInternalError(ses.GetRequestContext(), errorSystemVariableIsReadOnly())
   847  		}
   848  
   849  		cv, err := def.GetType().Convert(value)
   850  		if err != nil {
   851  			errutil.ReportError(ses.GetRequestContext(), err)
   852  			return err
   853  		}
   854  
   855  		if def.UpdateSessVar == nil {
   856  			ses.SetSysVar(def.GetName(), cv)
   857  		} else {
   858  			return def.UpdateSessVar(ses, ses.GetSysVars(), def.GetName(), cv)
   859  		}
   860  	} else {
   861  		return moerr.NewInternalError(ses.GetRequestContext(), errorSystemVariableDoesNotExist())
   862  	}
   863  	return nil
   864  }
   865  
   866  // GetSessionVar gets this value of the system variable in session
   867  func (ses *Session) GetSessionVar(name string) (interface{}, error) {
   868  	gSysVars := ses.GetGlobalSysVars()
   869  	if def, gVal, ok := gSysVars.GetGlobalSysVar(name); ok {
   870  		ciname := strings.ToLower(name)
   871  		if def.GetScope() == ScopeGlobal {
   872  			return gVal, nil
   873  		}
   874  		return ses.GetSysVar(ciname), nil
   875  	} else {
   876  		return nil, moerr.NewInternalError(ses.GetRequestContext(), errorSystemVariableDoesNotExist())
   877  	}
   878  }
   879  
   880  func (ses *Session) CopyAllSessionVars() map[string]interface{} {
   881  	ses.mu.Lock()
   882  	defer ses.mu.Unlock()
   883  	cp := make(map[string]interface{})
   884  	for k, v := range ses.sysVars {
   885  		cp[k] = v
   886  	}
   887  	return cp
   888  }
   889  
   890  // SetUserDefinedVar sets the user defined variable to the value in session
   891  func (ses *Session) SetUserDefinedVar(name string, value interface{}) error {
   892  	ses.mu.Lock()
   893  	defer ses.mu.Unlock()
   894  	ses.userDefinedVars[strings.ToLower(name)] = value
   895  	return nil
   896  }
   897  
   898  // GetUserDefinedVar gets value of the user defined variable
   899  func (ses *Session) GetUserDefinedVar(name string) (SystemVariableType, interface{}, error) {
   900  	ses.mu.Lock()
   901  	defer ses.mu.Unlock()
   902  	val, ok := ses.userDefinedVars[strings.ToLower(name)]
   903  	if !ok {
   904  		return SystemVariableNullType{}, nil, nil
   905  	}
   906  	return InitSystemVariableStringType(name), val, nil
   907  }
   908  
   909  func (ses *Session) GetTxnHandler() *TxnHandler {
   910  	ses.mu.Lock()
   911  	defer ses.mu.Unlock()
   912  	return ses.txnHandler
   913  }
   914  
   915  func (ses *Session) SetSql(sql string) {
   916  	ses.mu.Lock()
   917  	defer ses.mu.Unlock()
   918  	ses.sql = sql
   919  }
   920  
   921  func (ses *Session) GetSql() string {
   922  	ses.mu.Lock()
   923  	defer ses.mu.Unlock()
   924  	return ses.sql
   925  }
   926  
   927  func (ses *Session) IsTaeEngine() bool {
   928  	ses.mu.Lock()
   929  	defer ses.mu.Unlock()
   930  	e, isEntire := ses.storage.(*engine.EntireEngine)
   931  	if isEntire {
   932  		_, ok := e.Engine.(moengine.TxnEngine)
   933  		return ok
   934  	} else {
   935  		_, ok := ses.storage.(moengine.TxnEngine)
   936  		return ok
   937  	}
   938  }
   939  
   940  func (ses *Session) IsEntireEngine() bool {
   941  	ses.mu.Lock()
   942  	defer ses.mu.Unlock()
   943  	_, isEntire := ses.storage.(*engine.EntireEngine)
   944  	if isEntire {
   945  		return true
   946  	} else {
   947  		return false
   948  	}
   949  }
   950  
   951  func (ses *Session) GetStorage() engine.Engine {
   952  	ses.mu.Lock()
   953  	defer ses.mu.Unlock()
   954  	return ses.storage
   955  }
   956  
   957  func (ses *Session) SetTempEngine(ctx context.Context, te engine.Engine) error {
   958  	ses.mu.Lock()
   959  	defer ses.mu.Unlock()
   960  	ee := ses.storage.(*engine.EntireEngine)
   961  	ee.TempEngine = te
   962  	ses.requestCtx = ctx
   963  	return nil
   964  }
   965  
   966  func (ses *Session) GetDatabaseName() string {
   967  	return ses.GetMysqlProtocol().GetDatabaseName()
   968  }
   969  
   970  func (ses *Session) SetDatabaseName(db string) {
   971  	ses.GetMysqlProtocol().SetDatabaseName(db)
   972  	ses.GetTxnCompileCtx().SetDatabase(db)
   973  }
   974  
   975  func (ses *Session) DatabaseNameIsEmpty() bool {
   976  	return len(ses.GetDatabaseName()) == 0
   977  }
   978  
   979  func (ses *Session) GetUserName() string {
   980  	return ses.GetMysqlProtocol().GetUserName()
   981  }
   982  
   983  func (ses *Session) SetUserName(uname string) {
   984  	ses.GetMysqlProtocol().SetUserName(uname)
   985  }
   986  
   987  func (ses *Session) GetConnectionID() uint32 {
   988  	return ses.GetMysqlProtocol().ConnectionID()
   989  }
   990  
   991  func (ses *Session) GetPeer() (string, string) {
   992  	rh, rp, _, _ := ses.GetMysqlProtocol().Peer()
   993  	return rh, rp
   994  }
   995  
   996  func (ses *Session) SetOptionBits(bit uint32) {
   997  	ses.mu.Lock()
   998  	defer ses.mu.Unlock()
   999  	ses.optionBits |= bit
  1000  }
  1001  
  1002  func (ses *Session) ClearOptionBits(bit uint32) {
  1003  	ses.mu.Lock()
  1004  	defer ses.mu.Unlock()
  1005  	ses.optionBits &= ^bit
  1006  }
  1007  
  1008  func (ses *Session) OptionBitsIsSet(bit uint32) bool {
  1009  	ses.mu.Lock()
  1010  	defer ses.mu.Unlock()
  1011  	return ses.optionBits&bit != 0
  1012  }
  1013  
  1014  func (ses *Session) SetServerStatus(bit uint16) {
  1015  	ses.mu.Lock()
  1016  	defer ses.mu.Unlock()
  1017  	ses.serverStatus |= bit
  1018  }
  1019  
  1020  func (ses *Session) ClearServerStatus(bit uint16) {
  1021  	ses.mu.Lock()
  1022  	defer ses.mu.Unlock()
  1023  	ses.serverStatus &= ^bit
  1024  }
  1025  
  1026  func (ses *Session) ServerStatusIsSet(bit uint16) bool {
  1027  	ses.mu.Lock()
  1028  	defer ses.mu.Unlock()
  1029  	return ses.serverStatus&bit != 0
  1030  }
  1031  
  1032  /*
  1033  InMultiStmtTransactionMode checks the session is in multi-statement transaction mode.
  1034  OPTION_NOT_AUTOCOMMIT: After the autocommit is off, the multi-statement transaction is
  1035  started implicitly by the first statement of the transaction.
  1036  OPTION_BEGIN: Whenever the autocommit is on or off, the multi-statement transaction is
  1037  started explicitly by the BEGIN statement.
  1038  
  1039  But it does not denote the transaction is active or not.
  1040  
  1041  Cases    | set Autocommit = 1/0 | BEGIN statement |
  1042  ---------------------------------------------------
  1043  Case1      1                       Yes
  1044  Case2      1                       No
  1045  Case3      0                       Yes
  1046  Case4      0                       No
  1047  ---------------------------------------------------
  1048  
  1049  If it is Case1,Case3,Cass4, Then
  1050  
  1051  	InMultiStmtTransactionMode returns true.
  1052  	Also, the bit SERVER_STATUS_IN_TRANS will be set.
  1053  
  1054  If it is Case2, Then
  1055  
  1056  	InMultiStmtTransactionMode returns false
  1057  */
  1058  func (ses *Session) InMultiStmtTransactionMode() bool {
  1059  	return ses.OptionBitsIsSet(OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)
  1060  }
  1061  
  1062  /*
  1063  InActiveMultiStmtTransaction checks the session is in multi-statement transaction mode
  1064  and there is an active transaction.
  1065  
  1066  But sometimes, the session does not start an active transaction even if it is in multi-
  1067  statement transaction mode.
  1068  
  1069  For example: there is no active transaction.
  1070  set autocommit = 0;
  1071  select 1;
  1072  
  1073  For example: there is an active transaction.
  1074  begin;
  1075  select 1;
  1076  
  1077  When the statement starts the multi-statement transaction(select * from table), this flag
  1078  won't be set until we access the tables.
  1079  */
  1080  func (ses *Session) InActiveMultiStmtTransaction() bool {
  1081  	return ses.ServerStatusIsSet(SERVER_STATUS_IN_TRANS)
  1082  }
  1083  
  1084  /*
  1085  TxnStart starts the transaction implicitly and idempotent
  1086  
  1087  When it is in multi-statement transaction mode:
  1088  
  1089  	Set SERVER_STATUS_IN_TRANS bit;
  1090  	Starts a new transaction if there is none. Reuse the current transaction if there is one.
  1091  
  1092  When it is not in single statement transaction mode:
  1093  
  1094  	Starts a new transaction if there is none. Reuse the current transaction if there is one.
  1095  */
  1096  func (ses *Session) TxnStart() error {
  1097  	var err error
  1098  	if ses.InMultiStmtTransactionMode() {
  1099  		ses.SetServerStatus(SERVER_STATUS_IN_TRANS)
  1100  	}
  1101  	if !ses.GetTxnHandler().IsValidTxn() {
  1102  		err = ses.GetTxnHandler().NewTxn()
  1103  	}
  1104  	return err
  1105  }
  1106  
  1107  /*
  1108  TxnCommitSingleStatement commits the single statement transaction.
  1109  
  1110  Cases    | set Autocommit = 1/0 | BEGIN statement |
  1111  ---------------------------------------------------
  1112  Case1      1                       Yes
  1113  Case2      1                       No
  1114  Case3      0                       Yes
  1115  Case4      0                       No
  1116  ---------------------------------------------------
  1117  
  1118  If it is Case1,Case3,Cass4, Then
  1119  
  1120  	InMultiStmtTransactionMode returns true.
  1121  	Also, the bit SERVER_STATUS_IN_TRANS will be set.
  1122  
  1123  If it is Case2, Then
  1124  
  1125  	InMultiStmtTransactionMode returns false
  1126  */
  1127  func (ses *Session) TxnCommitSingleStatement(stmt tree.Statement) error {
  1128  	var err error
  1129  	/*
  1130  		Commit Rules:
  1131  		1, if it is in single-statement mode:
  1132  			it commits.
  1133  		2, if it is in multi-statement mode:
  1134  			if the statement is the one can be executed in the active transaction,
  1135  				the transaction need to be committed at the end of the statement.
  1136  	*/
  1137  	if !ses.InMultiStmtTransactionMode() ||
  1138  		ses.InActiveTransaction() && NeedToBeCommittedInActiveTransaction(stmt) {
  1139  		err = ses.GetTxnHandler().CommitTxn()
  1140  		ses.ClearServerStatus(SERVER_STATUS_IN_TRANS)
  1141  		ses.ClearOptionBits(OPTION_BEGIN)
  1142  	}
  1143  	return err
  1144  }
  1145  
  1146  /*
  1147  TxnRollbackSingleStatement rollbacks the single statement transaction.
  1148  
  1149  Cases    | set Autocommit = 1/0 | BEGIN statement |
  1150  ---------------------------------------------------
  1151  Case1      1                       Yes
  1152  Case2      1                       No
  1153  Case3      0                       Yes
  1154  Case4      0                       No
  1155  ---------------------------------------------------
  1156  
  1157  If it is Case1,Case3,Cass4, Then
  1158  
  1159  	InMultiStmtTransactionMode returns true.
  1160  	Also, the bit SERVER_STATUS_IN_TRANS will be set.
  1161  
  1162  If it is Case2, Then
  1163  
  1164  	InMultiStmtTransactionMode returns false
  1165  */
  1166  func (ses *Session) TxnRollbackSingleStatement(stmt tree.Statement) error {
  1167  	var err error
  1168  	/*
  1169  			Rollback Rules:
  1170  			1, if it is in single-statement mode (Case2):
  1171  				it rollbacks.
  1172  			2, if it is in multi-statement mode (Case1,Case3,Case4):
  1173  		        the transaction need to be rollback at the end of the statement.
  1174  				(every error will abort the transaction.)
  1175  	*/
  1176  	if !ses.InMultiStmtTransactionMode() ||
  1177  		ses.InActiveTransaction() {
  1178  		err = ses.GetTxnHandler().RollbackTxn()
  1179  		ses.ClearServerStatus(SERVER_STATUS_IN_TRANS)
  1180  		ses.ClearOptionBits(OPTION_BEGIN)
  1181  	}
  1182  	return err
  1183  }
  1184  
  1185  /*
  1186  TxnBegin begins a new transaction.
  1187  It commits the current transaction implicitly.
  1188  */
  1189  func (ses *Session) TxnBegin() error {
  1190  	var err error
  1191  	if ses.InMultiStmtTransactionMode() {
  1192  		ses.ClearServerStatus(SERVER_STATUS_IN_TRANS)
  1193  		err = ses.GetTxnHandler().CommitTxn()
  1194  	}
  1195  	ses.ClearOptionBits(OPTION_BEGIN)
  1196  	if err != nil {
  1197  		/*
  1198  			fix issue 6024.
  1199  			When we get a w-w conflict during commit the txn,
  1200  			we convert the error into a readable error.
  1201  		*/
  1202  		if moerr.IsMoErrCode(err, moerr.ErrTxnWWConflict) {
  1203  			return moerr.NewInternalError(ses.GetRequestContext(), writeWriteConflictsErrorInfo())
  1204  		}
  1205  		return err
  1206  	}
  1207  	ses.SetOptionBits(OPTION_BEGIN)
  1208  	ses.SetServerStatus(SERVER_STATUS_IN_TRANS)
  1209  	err = ses.GetTxnHandler().NewTxn()
  1210  	return err
  1211  }
  1212  
  1213  // TxnCommit commits the current transaction.
  1214  func (ses *Session) TxnCommit() error {
  1215  	var err error
  1216  	ses.ClearServerStatus(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY)
  1217  	err = ses.GetTxnHandler().CommitTxn()
  1218  	ses.ClearServerStatus(SERVER_STATUS_IN_TRANS)
  1219  	ses.ClearOptionBits(OPTION_BEGIN)
  1220  	return err
  1221  }
  1222  
  1223  // TxnRollback rollbacks the current transaction.
  1224  func (ses *Session) TxnRollback() error {
  1225  	var err error
  1226  	ses.ClearServerStatus(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY)
  1227  	err = ses.GetTxnHandler().RollbackTxn()
  1228  	ses.ClearOptionBits(OPTION_BEGIN)
  1229  	return err
  1230  }
  1231  
  1232  /*
  1233  InActiveTransaction checks if it is in an active transaction.
  1234  */
  1235  func (ses *Session) InActiveTransaction() bool {
  1236  	if ses.InActiveMultiStmtTransaction() {
  1237  		return true
  1238  	} else {
  1239  		return ses.GetTxnHandler().IsValidTxn()
  1240  	}
  1241  }
  1242  
  1243  /*
  1244  SetAutocommit sets the value of the system variable 'autocommit'.
  1245  
  1246  The rule is that we can not execute the statement 'set parameter = value' in
  1247  an active transaction whichever it is started by BEGIN or in 'set autocommit = 0;'.
  1248  */
  1249  func (ses *Session) SetAutocommit(on bool) error {
  1250  	if ses.InActiveTransaction() {
  1251  		return moerr.NewInternalError(ses.requestCtx, parameterModificationInTxnErrorInfo())
  1252  	}
  1253  	if on {
  1254  		ses.ClearOptionBits(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT)
  1255  		ses.SetServerStatus(SERVER_STATUS_AUTOCOMMIT)
  1256  	} else {
  1257  		ses.ClearServerStatus(SERVER_STATUS_AUTOCOMMIT)
  1258  		ses.SetOptionBits(OPTION_NOT_AUTOCOMMIT)
  1259  	}
  1260  	return nil
  1261  }
  1262  
  1263  func (ses *Session) SetOutputCallback(callback func(interface{}, *batch.Batch) error) {
  1264  	ses.mu.Lock()
  1265  	defer ses.mu.Unlock()
  1266  	ses.outputCallback = callback
  1267  }
  1268  
  1269  func (ses *Session) skipAuthForSpecialUser() bool {
  1270  	if ses.GetTenantInfo() != nil {
  1271  		ok, _, _ := isSpecialUser(ses.GetTenantInfo().GetUser())
  1272  		return ok
  1273  	}
  1274  	return false
  1275  }
  1276  
  1277  // AuthenticateUser verifies the password of the user.
  1278  func (ses *Session) AuthenticateUser(userInput string) ([]byte, error) {
  1279  	var defaultRoleID int64
  1280  	var defaultRole string
  1281  	var tenant *TenantInfo
  1282  	var err error
  1283  	var rsset []ExecResult
  1284  	var tenantID int64
  1285  	var userID int64
  1286  	var pwd, accountStatus string
  1287  	var pwdBytes []byte
  1288  	var isSpecial bool
  1289  	var specialAccount *TenantInfo
  1290  
  1291  	//Get tenant info
  1292  	tenant, err = GetTenantInfo(ses.GetRequestContext(), userInput)
  1293  	if err != nil {
  1294  		return nil, err
  1295  	}
  1296  
  1297  	ses.SetTenantInfo(tenant)
  1298  	ses.MakeProfile()
  1299  	sessionProfile := ses.GetConciseProfile()
  1300  
  1301  	logDebugf(sessionProfile, "check special user")
  1302  	// check the special user for initilization
  1303  	isSpecial, pwdBytes, specialAccount = isSpecialUser(tenant.GetUser())
  1304  	if isSpecial && specialAccount.IsMoAdminRole() {
  1305  		ses.SetTenantInfo(specialAccount)
  1306  		return pwdBytes, nil
  1307  	}
  1308  
  1309  	ses.SetTenantInfo(tenant)
  1310  
  1311  	//step1 : check tenant exists or not in SYS tenant context
  1312  	sysTenantCtx := context.WithValue(ses.GetRequestContext(), defines.TenantIDKey{}, uint32(sysAccountID))
  1313  	sysTenantCtx = context.WithValue(sysTenantCtx, defines.UserIDKey{}, uint32(rootID))
  1314  	sysTenantCtx = context.WithValue(sysTenantCtx, defines.RoleIDKey{}, uint32(moAdminRoleID))
  1315  	sqlForCheckTenant := getSqlForCheckTenant(tenant.GetTenant())
  1316  	pu := ses.GetParameterUnit()
  1317  	mp := ses.GetMemPool()
  1318  	logDebugf(sessionProfile, "check tenant %s exists", tenant)
  1319  	rsset, err = executeSQLInBackgroundSession(sysTenantCtx, mp, pu, sqlForCheckTenant, ses.GetAutoIncrCaches())
  1320  	if err != nil {
  1321  		return nil, err
  1322  	}
  1323  	if !execResultArrayHasData(rsset) {
  1324  		return nil, moerr.NewInternalError(sysTenantCtx, "there is no tenant %s", tenant.GetTenant())
  1325  	}
  1326  
  1327  	//account id
  1328  	tenantID, err = rsset[0].GetInt64(sysTenantCtx, 0, 0)
  1329  	if err != nil {
  1330  		return nil, err
  1331  	}
  1332  
  1333  	//account status
  1334  	accountStatus, err = rsset[0].GetString(sysTenantCtx, 0, 2)
  1335  	if err != nil {
  1336  		return nil, err
  1337  	}
  1338  
  1339  	if strings.ToLower(accountStatus) == tree.AccountStatusSuspend.String() {
  1340  		return nil, moerr.NewInternalError(sysTenantCtx, "Account %s is suspended", tenant.GetTenant())
  1341  	}
  1342  
  1343  	tenant.SetTenantID(uint32(tenantID))
  1344  	//step2 : check user exists or not in general tenant.
  1345  	//step3 : get the password of the user
  1346  
  1347  	tenantCtx := context.WithValue(ses.GetRequestContext(), defines.TenantIDKey{}, uint32(tenantID))
  1348  
  1349  	logDebugf(sessionProfile, "check user of %s exists", tenant)
  1350  	//Get the password of the user in an independent session
  1351  	sqlForPasswordOfUser := getSqlForPasswordOfUser(tenant.GetUser())
  1352  	rsset, err = executeSQLInBackgroundSession(tenantCtx, mp, pu, sqlForPasswordOfUser, ses.GetAutoIncrCaches())
  1353  	if err != nil {
  1354  		return nil, err
  1355  	}
  1356  	if !execResultArrayHasData(rsset) {
  1357  		return nil, moerr.NewInternalError(tenantCtx, "there is no user %s", tenant.GetUser())
  1358  	}
  1359  
  1360  	userID, err = rsset[0].GetInt64(tenantCtx, 0, 0)
  1361  	if err != nil {
  1362  		return nil, err
  1363  	}
  1364  
  1365  	pwd, err = rsset[0].GetString(tenantCtx, 0, 1)
  1366  	if err != nil {
  1367  		return nil, err
  1368  	}
  1369  
  1370  	//the default_role in the mo_user table.
  1371  	//the default_role is always valid. public or other valid role.
  1372  	defaultRoleID, err = rsset[0].GetInt64(tenantCtx, 0, 2)
  1373  	if err != nil {
  1374  		return nil, err
  1375  	}
  1376  
  1377  	tenant.SetUserID(uint32(userID))
  1378  	tenant.SetDefaultRoleID(uint32(defaultRoleID))
  1379  
  1380  	/*
  1381  		login case 1: tenant:user
  1382  		1.get the default_role of the user in mo_user
  1383  
  1384  		login case 2: tenant:user:role
  1385  		1.check the role has been granted to the user
  1386  			-yes: go on
  1387  			-no: error
  1388  
  1389  	*/
  1390  	//it denotes that there is no default role in the input
  1391  	if tenant.HasDefaultRole() {
  1392  		logDebugf(sessionProfile, "check default role of user %s.", tenant)
  1393  		//step4 : check role exists or not
  1394  		sqlForCheckRoleExists := getSqlForRoleIdOfRole(tenant.GetDefaultRole())
  1395  		rsset, err = executeSQLInBackgroundSession(tenantCtx, mp, pu, sqlForCheckRoleExists, ses.GetAutoIncrCaches())
  1396  		if err != nil {
  1397  			return nil, err
  1398  		}
  1399  
  1400  		if !execResultArrayHasData(rsset) {
  1401  			return nil, moerr.NewInternalError(tenantCtx, "there is no role %s", tenant.GetDefaultRole())
  1402  		}
  1403  
  1404  		logDebugf(sessionProfile, "check granted role of user %s.", tenant)
  1405  		//step4.2 : check the role has been granted to the user or not
  1406  		sqlForRoleOfUser := getSqlForRoleOfUser(userID, tenant.GetDefaultRole())
  1407  		rsset, err = executeSQLInBackgroundSession(tenantCtx, mp, pu, sqlForRoleOfUser, ses.GetAutoIncrCaches())
  1408  		if err != nil {
  1409  			return nil, err
  1410  		}
  1411  		if !execResultArrayHasData(rsset) {
  1412  			return nil, moerr.NewInternalError(tenantCtx, "the role %s has not been granted to the user %s",
  1413  				tenant.GetDefaultRole(), tenant.GetUser())
  1414  		}
  1415  
  1416  		defaultRoleID, err = rsset[0].GetInt64(tenantCtx, 0, 0)
  1417  		if err != nil {
  1418  			return nil, err
  1419  		}
  1420  		tenant.SetDefaultRoleID(uint32(defaultRoleID))
  1421  	} else {
  1422  		logDebugf(sessionProfile, "check designated role of user %s.", tenant)
  1423  		//the get name of default_role from mo_role
  1424  		sql := getSqlForRoleNameOfRoleId(defaultRoleID)
  1425  		rsset, err = executeSQLInBackgroundSession(tenantCtx, mp, pu, sql, ses.GetAutoIncrCaches())
  1426  		if err != nil {
  1427  			return nil, err
  1428  		}
  1429  		if !execResultArrayHasData(rsset) {
  1430  			return nil, moerr.NewInternalError(tenantCtx, "get the default role of the user %s failed", tenant.GetUser())
  1431  		}
  1432  
  1433  		defaultRole, err = rsset[0].GetString(tenantCtx, 0, 0)
  1434  		if err != nil {
  1435  			return nil, err
  1436  		}
  1437  		tenant.SetDefaultRole(defaultRole)
  1438  	}
  1439  
  1440  	logInfo(sessionProfile, tenant.String())
  1441  
  1442  	return []byte(pwd), nil
  1443  }
  1444  
  1445  func (ses *Session) GetPrivilege() *privilege {
  1446  	ses.mu.Lock()
  1447  	defer ses.mu.Unlock()
  1448  	return ses.priv
  1449  }
  1450  
  1451  func (ses *Session) SetPrivilege(priv *privilege) {
  1452  	ses.mu.Lock()
  1453  	defer ses.mu.Unlock()
  1454  	ses.priv = priv
  1455  }
  1456  
  1457  func (ses *Session) SetFromRealUser(b bool) {
  1458  	ses.mu.Lock()
  1459  	defer ses.mu.Unlock()
  1460  	ses.fromRealUser = b
  1461  }
  1462  
  1463  func (ses *Session) GetFromRealUser() bool {
  1464  	ses.mu.Lock()
  1465  	defer ses.mu.Unlock()
  1466  	return ses.fromRealUser
  1467  }
  1468  
  1469  func (th *TxnHandler) SetSession(ses *Session) {
  1470  	th.mu.Lock()
  1471  	defer th.mu.Unlock()
  1472  	th.ses = ses
  1473  }
  1474  
  1475  func (th *TxnHandler) GetTxnClient() TxnClient {
  1476  	th.mu.Lock()
  1477  	defer th.mu.Unlock()
  1478  	return th.txnClient
  1479  }
  1480  
  1481  // TxnClientNew creates a new txn
  1482  func (th *TxnHandler) TxnClientNew() error {
  1483  	var err error
  1484  	th.mu.Lock()
  1485  	defer th.mu.Unlock()
  1486  	if th.txnClient == nil {
  1487  		panic("must set txn client")
  1488  	}
  1489  
  1490  	var opts []client.TxnOption
  1491  	rt := moruntime.ProcessLevelRuntime()
  1492  	if rt != nil {
  1493  		if v, ok := rt.GetGlobalVariables(moruntime.TxnOptions); ok {
  1494  			opts = v.([]client.TxnOption)
  1495  		}
  1496  	}
  1497  
  1498  	th.txn, err = th.txnClient.New(opts...)
  1499  	if err != nil {
  1500  		return err
  1501  	}
  1502  	if th.txn == nil {
  1503  		return moerr.NewInternalError(th.ses.GetRequestContext(), "TxnClientNew: txnClient new a null txn")
  1504  	}
  1505  	return err
  1506  }
  1507  
  1508  // NewTxn commits the old transaction if it existed.
  1509  // Then it creates the new transaction.
  1510  func (th *TxnHandler) NewTxn() error {
  1511  	var err error
  1512  	ctx := th.GetSession().GetRequestContext()
  1513  	if th.IsValidTxn() {
  1514  		err = th.CommitTxn()
  1515  		if err != nil {
  1516  			/*
  1517  				fix issue 6024.
  1518  				When we get a w-w conflict during commit the txn,
  1519  				we convert the error into a readable error.
  1520  			*/
  1521  			if moerr.IsMoErrCode(err, moerr.ErrTxnWWConflict) {
  1522  				return moerr.NewInternalError(ctx, writeWriteConflictsErrorInfo())
  1523  			}
  1524  			return err
  1525  		}
  1526  	}
  1527  	th.SetInvalid()
  1528  	defer func() {
  1529  		if err != nil {
  1530  			tenant := th.ses.GetTenantName(nil)
  1531  			incTransactionErrorsCounter(tenant, metric.SQLTypeBegin)
  1532  		}
  1533  	}()
  1534  	err = th.TxnClientNew()
  1535  	if err != nil {
  1536  		return err
  1537  	}
  1538  	if ctx == nil {
  1539  		panic("context should not be nil")
  1540  	}
  1541  	storage := th.GetStorage()
  1542  	err = storage.New(ctx, th.GetTxnOperator())
  1543  	return err
  1544  }
  1545  
  1546  // IsValidTxn checks the transaction is true or not.
  1547  func (th *TxnHandler) IsValidTxn() bool {
  1548  	th.mu.Lock()
  1549  	defer th.mu.Unlock()
  1550  	return th.txn != nil
  1551  }
  1552  
  1553  func (th *TxnHandler) SetInvalid() {
  1554  	th.mu.Lock()
  1555  	defer th.mu.Unlock()
  1556  	th.txn = nil
  1557  }
  1558  
  1559  func (th *TxnHandler) GetTxnOperator() TxnOperator {
  1560  	th.mu.Lock()
  1561  	defer th.mu.Unlock()
  1562  	return th.txn
  1563  }
  1564  
  1565  func (th *TxnHandler) GetSession() *Session {
  1566  	th.mu.Lock()
  1567  	defer th.mu.Unlock()
  1568  	return th.ses
  1569  }
  1570  
  1571  func (th *TxnHandler) CommitTxn() error {
  1572  	th.entryMu.Lock()
  1573  	defer th.entryMu.Unlock()
  1574  	if !th.IsValidTxn() {
  1575  		return nil
  1576  	}
  1577  	ses := th.GetSession()
  1578  	sessionProfile := ses.GetConciseProfile()
  1579  	ctx := ses.GetRequestContext()
  1580  	if ctx == nil {
  1581  		panic("context should not be nil")
  1582  	}
  1583  	if ses.tempTablestorage != nil {
  1584  		ctx = context.WithValue(ctx, defines.TemporaryDN{}, ses.tempTablestorage)
  1585  	}
  1586  	storage := th.GetStorage()
  1587  	ctx, cancel := context.WithTimeout(
  1588  		ctx,
  1589  		storage.Hints().CommitOrRollbackTimeout,
  1590  	)
  1591  	defer cancel()
  1592  	var err, err2 error
  1593  	defer func() {
  1594  		// metric count
  1595  		tenant := ses.GetTenantName(nil)
  1596  		incTransactionCounter(tenant)
  1597  		if err != nil {
  1598  			incTransactionErrorsCounter(tenant, metric.SQLTypeCommit)
  1599  		}
  1600  	}()
  1601  	txnOp := th.GetTxnOperator()
  1602  	if txnOp == nil {
  1603  		logErrorf(sessionProfile, "CommitTxn: txn operator is null")
  1604  	}
  1605  
  1606  	txnId := txnOp.Txn().DebugString()
  1607  	logDebugf(sessionProfile, "CommitTxn txnId:%s", txnId)
  1608  	defer func() {
  1609  		logDebugf(sessionProfile, "CommitTxn exit txnId:%s", txnId)
  1610  	}()
  1611  	if err = storage.Commit(ctx, txnOp); err != nil {
  1612  		th.SetInvalid()
  1613  		logErrorf(sessionProfile, "CommitTxn: storage commit failed. txnId:%s error:%v", txnId, err)
  1614  		if txnOp != nil {
  1615  			err2 = txnOp.Rollback(ctx)
  1616  			if err2 != nil {
  1617  				logErrorf(sessionProfile, "CommitTxn: txn operator rollback failed. txnId:%s error:%v", txnId, err2)
  1618  			}
  1619  		}
  1620  		return err
  1621  	}
  1622  	if txnOp != nil {
  1623  		err = txnOp.Commit(ctx)
  1624  		if err != nil {
  1625  			th.SetInvalid()
  1626  			logErrorf(sessionProfile, "CommitTxn: txn operator commit failed. txnId:%s error:%v", txnId, err)
  1627  		}
  1628  	}
  1629  	th.SetInvalid()
  1630  	return err
  1631  }
  1632  
  1633  func (th *TxnHandler) RollbackTxn() error {
  1634  	th.entryMu.Lock()
  1635  	defer th.entryMu.Unlock()
  1636  	if !th.IsValidTxn() {
  1637  		return nil
  1638  	}
  1639  	ses := th.GetSession()
  1640  	sessionProfile := ses.GetConciseProfile()
  1641  	ctx := ses.GetRequestContext()
  1642  	if ctx == nil {
  1643  		panic("context should not be nil")
  1644  	}
  1645  	if ses.tempTablestorage != nil {
  1646  		ctx = context.WithValue(ctx, defines.TemporaryDN{}, ses.tempTablestorage)
  1647  	}
  1648  	storage := th.GetStorage()
  1649  	ctx, cancel := context.WithTimeout(
  1650  		ctx,
  1651  		storage.Hints().CommitOrRollbackTimeout,
  1652  	)
  1653  	defer cancel()
  1654  	var err, err2 error
  1655  	defer func() {
  1656  		// metric count
  1657  		tenant := ses.GetTenantName(nil)
  1658  		incTransactionCounter(tenant)
  1659  		incTransactionErrorsCounter(tenant, metric.SQLTypeOther) // exec rollback cnt
  1660  		if err != nil {
  1661  			incTransactionErrorsCounter(tenant, metric.SQLTypeRollback)
  1662  		}
  1663  	}()
  1664  	txnOp := th.GetTxnOperator()
  1665  	if txnOp == nil {
  1666  		logErrorf(sessionProfile, "RollbackTxn: txn operator is null")
  1667  	}
  1668  	txnId := txnOp.Txn().DebugString()
  1669  	logDebugf(sessionProfile, "RollbackTxn txnId:%s", txnId)
  1670  	defer func() {
  1671  		logDebugf(sessionProfile, "RollbackTxn exit txnId:%s", txnId)
  1672  	}()
  1673  	if err = storage.Rollback(ctx, txnOp); err != nil {
  1674  		th.SetInvalid()
  1675  		logErrorf(sessionProfile, "RollbackTxn: storage rollback failed. txnId:%s error:%v", txnId, err)
  1676  		if txnOp != nil {
  1677  			err2 = txnOp.Rollback(ctx)
  1678  			if err2 != nil {
  1679  				logErrorf(sessionProfile, "RollbackTxn: txn operator rollback failed. txnId:%s error:%v", txnId, err2)
  1680  			}
  1681  		}
  1682  		return err
  1683  	}
  1684  	if txnOp != nil {
  1685  		err = txnOp.Rollback(ctx)
  1686  		if err != nil {
  1687  			th.SetInvalid()
  1688  			logErrorf(sessionProfile, "RollbackTxn: txn operator commit failed. txnId:%s error:%v", txnId, err)
  1689  		}
  1690  	}
  1691  	th.SetInvalid()
  1692  	return err
  1693  }
  1694  
  1695  func (th *TxnHandler) GetStorage() engine.Engine {
  1696  	th.mu.Lock()
  1697  	defer th.mu.Unlock()
  1698  	return th.storage
  1699  }
  1700  
  1701  func (th *TxnHandler) GetTxn() (TxnOperator, error) {
  1702  	err := th.GetSession().TxnStart()
  1703  	if err != nil {
  1704  		logutil.Errorf("GetTxn. error:%v", err)
  1705  		return nil, err
  1706  	}
  1707  	return th.GetTxnOperator(), nil
  1708  }
  1709  
  1710  func (th *TxnHandler) GetTxnOnly() TxnOperator {
  1711  	th.mu.Lock()
  1712  	defer th.mu.Unlock()
  1713  	return th.txn
  1714  }
  1715  
  1716  var _ plan2.CompilerContext = &TxnCompilerContext{}
  1717  
  1718  type QueryType int
  1719  
  1720  const (
  1721  	TXN_DEFAULT QueryType = iota
  1722  	TXN_DELETE
  1723  	TXN_UPDATE
  1724  )
  1725  
  1726  type TxnCompilerContext struct {
  1727  	dbName               string
  1728  	QryTyp               QueryType
  1729  	txnHandler           *TxnHandler
  1730  	ses                  *Session
  1731  	proc                 *process.Process
  1732  	buildAlterView       bool
  1733  	dbOfView, nameOfView string
  1734  	mu                   sync.Mutex
  1735  }
  1736  
  1737  func (tcc *TxnCompilerContext) SetBuildingAlterView(yesOrNo bool, dbName, viewName string) {
  1738  	tcc.mu.Lock()
  1739  	defer tcc.mu.Unlock()
  1740  	tcc.buildAlterView = yesOrNo
  1741  	tcc.dbOfView = dbName
  1742  	tcc.nameOfView = viewName
  1743  }
  1744  
  1745  func (tcc *TxnCompilerContext) GetBuildingAlterView() (bool, string, string) {
  1746  	tcc.mu.Lock()
  1747  	defer tcc.mu.Unlock()
  1748  	return tcc.buildAlterView, tcc.dbOfView, tcc.nameOfView
  1749  }
  1750  
  1751  func InitTxnCompilerContext(txn *TxnHandler, db string) *TxnCompilerContext {
  1752  	return &TxnCompilerContext{txnHandler: txn, dbName: db, QryTyp: TXN_DEFAULT}
  1753  }
  1754  
  1755  func (tcc *TxnCompilerContext) GetQueryType() QueryType {
  1756  	tcc.mu.Lock()
  1757  	defer tcc.mu.Unlock()
  1758  	return tcc.QryTyp
  1759  }
  1760  
  1761  func (tcc *TxnCompilerContext) SetSession(ses *Session) {
  1762  	tcc.mu.Lock()
  1763  	defer tcc.mu.Unlock()
  1764  	tcc.ses = ses
  1765  }
  1766  
  1767  func (tcc *TxnCompilerContext) GetSession() *Session {
  1768  	tcc.mu.Lock()
  1769  	defer tcc.mu.Unlock()
  1770  	return tcc.ses
  1771  }
  1772  
  1773  func (tcc *TxnCompilerContext) GetTxnHandler() *TxnHandler {
  1774  	tcc.mu.Lock()
  1775  	defer tcc.mu.Unlock()
  1776  	return tcc.txnHandler
  1777  }
  1778  
  1779  func (tcc *TxnCompilerContext) GetUserName() string {
  1780  	tcc.mu.Lock()
  1781  	defer tcc.mu.Unlock()
  1782  	return tcc.ses.GetUserName()
  1783  }
  1784  
  1785  func (tcc *TxnCompilerContext) SetQueryType(qryTyp QueryType) {
  1786  	tcc.mu.Lock()
  1787  	defer tcc.mu.Unlock()
  1788  	tcc.QryTyp = qryTyp
  1789  }
  1790  
  1791  func (tcc *TxnCompilerContext) SetDatabase(db string) {
  1792  	tcc.mu.Lock()
  1793  	defer tcc.mu.Unlock()
  1794  	tcc.dbName = db
  1795  }
  1796  
  1797  func (tcc *TxnCompilerContext) DefaultDatabase() string {
  1798  	tcc.mu.Lock()
  1799  	defer tcc.mu.Unlock()
  1800  	return tcc.dbName
  1801  }
  1802  
  1803  func (tcc *TxnCompilerContext) GetRootSql() string {
  1804  	return tcc.GetSession().GetSql()
  1805  }
  1806  
  1807  func (tcc *TxnCompilerContext) GetAccountId() uint32 {
  1808  	return tcc.ses.accountId
  1809  }
  1810  
  1811  func (tcc *TxnCompilerContext) GetContext() context.Context {
  1812  	return tcc.ses.requestCtx
  1813  }
  1814  
  1815  func (tcc *TxnCompilerContext) DatabaseExists(name string) bool {
  1816  	var err error
  1817  	var txn TxnOperator
  1818  	txn, err = tcc.GetTxnHandler().GetTxn()
  1819  	if err != nil {
  1820  		return false
  1821  	}
  1822  	//open database
  1823  	ses := tcc.GetSession()
  1824  	_, err = tcc.GetTxnHandler().GetStorage().Database(ses.GetRequestContext(), name, txn)
  1825  	if err != nil {
  1826  		logErrorf(ses.GetConciseProfile(), "get database %v failed. error %v", name, err)
  1827  		return false
  1828  	}
  1829  
  1830  	return true
  1831  }
  1832  
  1833  // getRelation returns the context (maybe updated) and the relation
  1834  func (tcc *TxnCompilerContext) getRelation(dbName string, tableName string) (context.Context, engine.Relation, error) {
  1835  	dbName, err := tcc.ensureDatabaseIsNotEmpty(dbName)
  1836  	if err != nil {
  1837  		return nil, nil, err
  1838  	}
  1839  
  1840  	ses := tcc.GetSession()
  1841  	ctx := ses.GetRequestContext()
  1842  	account := ses.GetTenantInfo()
  1843  	if isClusterTable(dbName, tableName) {
  1844  		//if it is the cluster table in the general account, switch into the sys account
  1845  		if account != nil && account.GetTenantID() != sysAccountID {
  1846  			ctx = context.WithValue(ctx, defines.TenantIDKey{}, uint32(sysAccountID))
  1847  		}
  1848  	}
  1849  
  1850  	txn, err := tcc.GetTxnHandler().GetTxn()
  1851  	if err != nil {
  1852  		return nil, nil, err
  1853  	}
  1854  
  1855  	//open database
  1856  	db, err := tcc.GetTxnHandler().GetStorage().Database(ctx, dbName, txn)
  1857  	if err != nil {
  1858  		logErrorf(ses.GetConciseProfile(), "get database %v error %v", dbName, err)
  1859  		return nil, nil, err
  1860  	}
  1861  
  1862  	// tableNames, err := db.Relations(ctx)
  1863  	// if err != nil {
  1864  	// 	return nil, nil, err
  1865  	// }
  1866  	// logDebugf(ses.GetConciseProfile(), "dbName %v tableNames %v", dbName, tableNames)
  1867  
  1868  	//open table
  1869  	table, err := db.Relation(ctx, tableName)
  1870  	if err != nil {
  1871  		tmpTable, e := tcc.getTmpRelation(ctx, engine.GetTempTableName(dbName, tableName))
  1872  		if e != nil {
  1873  			logutil.Errorf("get table %v error %v", tableName, err)
  1874  			return nil, nil, err
  1875  		} else {
  1876  			table = tmpTable
  1877  		}
  1878  	}
  1879  	return ctx, table, nil
  1880  }
  1881  
  1882  func (tcc *TxnCompilerContext) getTmpRelation(ctx context.Context, tableName string) (engine.Relation, error) {
  1883  	e := tcc.ses.storage
  1884  	txn, err := tcc.txnHandler.GetTxn()
  1885  	if err != nil {
  1886  		return nil, err
  1887  	}
  1888  	db, err := e.Database(ctx, defines.TEMPORARY_DBNAME, txn)
  1889  	if err != nil {
  1890  		logutil.Errorf("get temp database error %v", err)
  1891  		return nil, err
  1892  	}
  1893  	table, err := db.Relation(ctx, tableName)
  1894  	return table, err
  1895  }
  1896  
  1897  func (tcc *TxnCompilerContext) ensureDatabaseIsNotEmpty(dbName string) (string, error) {
  1898  	if len(dbName) == 0 {
  1899  		dbName = tcc.DefaultDatabase()
  1900  	}
  1901  	if len(dbName) == 0 {
  1902  		return "", moerr.NewNoDB(tcc.GetContext())
  1903  	}
  1904  	return dbName, nil
  1905  }
  1906  
  1907  func (tcc *TxnCompilerContext) ResolveById(tableId uint64) (*plan2.ObjectRef, *plan2.TableDef) {
  1908  	ses := tcc.GetSession()
  1909  	ctx := ses.GetRequestContext()
  1910  	txn, err := tcc.GetTxnHandler().GetTxn()
  1911  	if err != nil {
  1912  		return nil, nil
  1913  	}
  1914  	dbName, tableName, table, err := tcc.GetTxnHandler().GetStorage().GetRelationById(ctx, txn, tableId)
  1915  	if err != nil {
  1916  		return nil, nil
  1917  	}
  1918  	return tcc.getTableDef(ctx, table, dbName, tableName)
  1919  }
  1920  
  1921  func (tcc *TxnCompilerContext) Resolve(dbName string, tableName string) (*plan2.ObjectRef, *plan2.TableDef) {
  1922  	dbName, err := tcc.ensureDatabaseIsNotEmpty(dbName)
  1923  	if err != nil {
  1924  		return nil, nil
  1925  	}
  1926  	ctx, table, err := tcc.getRelation(dbName, tableName)
  1927  	if err != nil {
  1928  		return nil, nil
  1929  	}
  1930  	return tcc.getTableDef(ctx, table, dbName, tableName)
  1931  }
  1932  
  1933  func (tcc *TxnCompilerContext) getTableDef(ctx context.Context, table engine.Relation, dbName, tableName string) (*plan2.ObjectRef, *plan2.TableDef) {
  1934  	tableId := table.GetTableID(ctx)
  1935  	engineDefs, err := table.TableDefs(ctx)
  1936  	if err != nil {
  1937  		return nil, nil
  1938  	}
  1939  
  1940  	var clusterByDef *plan2.ClusterByDef
  1941  	var cols []*plan2.ColDef
  1942  	var defs []*plan2.TableDefType
  1943  	var properties []*plan2.Property
  1944  	var TableType, Createsql string
  1945  	var CompositePkey *plan2.ColDef = nil
  1946  	var partitionInfo *plan2.PartitionByDef
  1947  	var viewSql *plan2.ViewDef
  1948  	var foreignKeys []*plan2.ForeignKeyDef
  1949  	var primarykey *plan2.PrimaryKeyDef
  1950  	var indexes []*plan2.IndexDef
  1951  	var refChildTbls []uint64
  1952  	for _, def := range engineDefs {
  1953  		if attr, ok := def.(*engine.AttributeDef); ok {
  1954  			isCPkey := util.JudgeIsCompositePrimaryKeyColumn(attr.Attr.Name)
  1955  			col := &plan2.ColDef{
  1956  				ColId: attr.Attr.ID,
  1957  				Name:  attr.Attr.Name,
  1958  				Typ: &plan2.Type{
  1959  					Id:          int32(attr.Attr.Type.Oid),
  1960  					Width:       attr.Attr.Type.Width,
  1961  					Precision:   attr.Attr.Type.Precision,
  1962  					Scale:       attr.Attr.Type.Scale,
  1963  					AutoIncr:    attr.Attr.AutoIncrement,
  1964  					Table:       tableName,
  1965  					NotNullable: attr.Attr.Default != nil && !attr.Attr.Default.NullAbility,
  1966  				},
  1967  				Primary:   attr.Attr.Primary,
  1968  				Default:   attr.Attr.Default,
  1969  				OnUpdate:  attr.Attr.OnUpdate,
  1970  				Comment:   attr.Attr.Comment,
  1971  				ClusterBy: attr.Attr.ClusterBy,
  1972  			}
  1973  			if isCPkey {
  1974  				CompositePkey = col
  1975  				continue
  1976  			}
  1977  			if attr.Attr.ClusterBy {
  1978  				clusterByDef = &plan.ClusterByDef{
  1979  					Name: attr.Attr.Name,
  1980  				}
  1981  				if util.JudgeIsCompositeClusterByColumn(attr.Attr.Name) {
  1982  					continue
  1983  				}
  1984  			}
  1985  			cols = append(cols, col)
  1986  		} else if pro, ok := def.(*engine.PropertiesDef); ok {
  1987  			for _, p := range pro.Properties {
  1988  				switch p.Key {
  1989  				case catalog.SystemRelAttr_Kind:
  1990  					TableType = p.Value
  1991  				case catalog.SystemRelAttr_CreateSQL:
  1992  					Createsql = p.Value
  1993  				default:
  1994  				}
  1995  				properties = append(properties, &plan2.Property{
  1996  					Key:   p.Key,
  1997  					Value: p.Value,
  1998  				})
  1999  			}
  2000  		} else if viewDef, ok := def.(*engine.ViewDef); ok {
  2001  			viewSql = &plan2.ViewDef{
  2002  				View: viewDef.View,
  2003  			}
  2004  		} else if c, ok := def.(*engine.ConstraintDef); ok {
  2005  			for _, ct := range c.Cts {
  2006  				switch k := ct.(type) {
  2007  				case *engine.IndexDef:
  2008  					indexes = k.Indexes
  2009  				case *engine.ForeignKeyDef:
  2010  					foreignKeys = k.Fkeys
  2011  				case *engine.RefChildTableDef:
  2012  					refChildTbls = k.Tables
  2013  				case *engine.PrimaryKeyDef:
  2014  					primarykey = k.Pkey
  2015  				}
  2016  			}
  2017  		} else if commnetDef, ok := def.(*engine.CommentDef); ok {
  2018  			properties = append(properties, &plan2.Property{
  2019  				Key:   catalog.SystemRelAttr_Comment,
  2020  				Value: commnetDef.Comment,
  2021  			})
  2022  		} else if partitionDef, ok := def.(*engine.PartitionDef); ok {
  2023  			p := &plan2.PartitionByDef{}
  2024  			err = p.UnMarshalPartitionInfo(([]byte)(partitionDef.Partition))
  2025  			if err != nil {
  2026  				return nil, nil
  2027  			}
  2028  			partitionInfo = p
  2029  		}
  2030  	}
  2031  	if len(properties) > 0 {
  2032  		defs = append(defs, &plan2.TableDefType{
  2033  			Def: &plan2.TableDef_DefType_Properties{
  2034  				Properties: &plan2.PropertiesDef{
  2035  					Properties: properties,
  2036  				},
  2037  			},
  2038  		})
  2039  	}
  2040  
  2041  	if tcc.GetQueryType() != TXN_DEFAULT {
  2042  		hideKeys, err := table.GetHideKeys(ctx)
  2043  		if err != nil {
  2044  			return nil, nil
  2045  		}
  2046  		hideKey := hideKeys[0]
  2047  		cols = append(cols, &plan2.ColDef{
  2048  			Name: hideKey.Name,
  2049  			Typ: &plan2.Type{
  2050  				Id:        int32(hideKey.Type.Oid),
  2051  				Width:     hideKey.Type.Width,
  2052  				Precision: hideKey.Type.Precision,
  2053  				Scale:     hideKey.Type.Scale,
  2054  			},
  2055  			Primary: hideKey.Primary,
  2056  		})
  2057  	}
  2058  
  2059  	//convert
  2060  	obj := &plan2.ObjectRef{
  2061  		SchemaName: dbName,
  2062  		ObjName:    tableName,
  2063  	}
  2064  	originCols := make([]*plan2.ColDef, len(cols))
  2065  	for i, col := range cols {
  2066  		originCols[i] = plan2.DeepCopyColDef(col)
  2067  	}
  2068  
  2069  	tableDef := &plan2.TableDef{
  2070  		TblId:         tableId,
  2071  		Name:          tableName,
  2072  		Cols:          cols,
  2073  		Defs:          defs,
  2074  		TableType:     TableType,
  2075  		Createsql:     Createsql,
  2076  		Pkey:          primarykey,
  2077  		CompositePkey: CompositePkey,
  2078  		ViewSql:       viewSql,
  2079  		Partition:     partitionInfo,
  2080  		Fkeys:         foreignKeys,
  2081  		RefChildTbls:  refChildTbls,
  2082  		ClusterBy:     clusterByDef,
  2083  		OriginCols:    originCols,
  2084  		Indexes:       indexes,
  2085  	}
  2086  	return obj, tableDef
  2087  }
  2088  
  2089  func (tcc *TxnCompilerContext) ResolveVariable(varName string, isSystemVar, isGlobalVar bool) (interface{}, error) {
  2090  	if isSystemVar {
  2091  		if isGlobalVar {
  2092  			return tcc.GetSession().GetGlobalVar(varName)
  2093  		} else {
  2094  			return tcc.GetSession().GetSessionVar(varName)
  2095  		}
  2096  	} else {
  2097  		_, val, err := tcc.GetSession().GetUserDefinedVar(varName)
  2098  		return val, err
  2099  	}
  2100  }
  2101  
  2102  func (tcc *TxnCompilerContext) ResolveAccountIds(accountNames []string) ([]uint32, error) {
  2103  	var err error
  2104  	var sql string
  2105  	var accountIds []uint32
  2106  	var erArray []ExecResult
  2107  	var targetAccountId uint64
  2108  	if len(accountNames) == 0 {
  2109  		return []uint32{}, nil
  2110  	}
  2111  
  2112  	dedup := make(map[string]int8)
  2113  	for _, name := range accountNames {
  2114  		dedup[name] = 1
  2115  	}
  2116  
  2117  	ses := tcc.GetSession()
  2118  	ctx := ses.GetRequestContext()
  2119  	bh := ses.GetBackgroundExec(ctx)
  2120  	defer bh.Close()
  2121  
  2122  	err = bh.Exec(ctx, "begin;")
  2123  	if err != nil {
  2124  		goto handleFailed
  2125  	}
  2126  
  2127  	for name := range dedup {
  2128  		sql = getSqlForCheckTenant(name)
  2129  		bh.ClearExecResultSet()
  2130  		err = bh.Exec(ctx, sql)
  2131  		if err != nil {
  2132  			goto handleFailed
  2133  		}
  2134  
  2135  		erArray, err = getResultSet(ctx, bh)
  2136  		if err != nil {
  2137  			goto handleFailed
  2138  		}
  2139  
  2140  		if execResultArrayHasData(erArray) {
  2141  			for i := uint64(0); i < erArray[0].GetRowCount(); i++ {
  2142  				targetAccountId, err = erArray[0].GetUint64(ctx, i, 0)
  2143  				if err != nil {
  2144  					goto handleFailed
  2145  				}
  2146  			}
  2147  			accountIds = append(accountIds, uint32(targetAccountId))
  2148  		} else {
  2149  			return nil, moerr.NewInternalError(ctx, "there is no account %s", name)
  2150  		}
  2151  	}
  2152  
  2153  	err = bh.Exec(ctx, "commit;")
  2154  	if err != nil {
  2155  		goto handleFailed
  2156  	}
  2157  	return accountIds, err
  2158  handleFailed:
  2159  	//ROLLBACK the transaction
  2160  	rbErr := bh.Exec(ctx, "rollback;")
  2161  	if rbErr != nil {
  2162  		return nil, rbErr
  2163  	}
  2164  	return nil, err
  2165  }
  2166  
  2167  func (tcc *TxnCompilerContext) GetPrimaryKeyDef(dbName string, tableName string) []*plan2.ColDef {
  2168  	dbName, err := tcc.ensureDatabaseIsNotEmpty(dbName)
  2169  	if err != nil {
  2170  		return nil
  2171  	}
  2172  	ctx, relation, err := tcc.getRelation(dbName, tableName)
  2173  	if err != nil {
  2174  		return nil
  2175  	}
  2176  
  2177  	priKeys, err := relation.GetPrimaryKeys(ctx)
  2178  	if err != nil {
  2179  		return nil
  2180  	}
  2181  	if len(priKeys) == 0 {
  2182  		return nil
  2183  	}
  2184  
  2185  	priDefs := make([]*plan2.ColDef, 0, len(priKeys))
  2186  	for _, key := range priKeys {
  2187  		priDefs = append(priDefs, &plan2.ColDef{
  2188  			Name: key.Name,
  2189  			Typ: &plan2.Type{
  2190  				Id:        int32(key.Type.Oid),
  2191  				Width:     key.Type.Width,
  2192  				Precision: key.Type.Precision,
  2193  				Scale:     key.Type.Scale,
  2194  				Size:      key.Type.Size,
  2195  			},
  2196  			Primary: key.Primary,
  2197  		})
  2198  	}
  2199  	return priDefs
  2200  }
  2201  
  2202  func (tcc *TxnCompilerContext) GetHideKeyDef(dbName string, tableName string) *plan2.ColDef {
  2203  	dbName, err := tcc.ensureDatabaseIsNotEmpty(dbName)
  2204  	if err != nil {
  2205  		return nil
  2206  	}
  2207  	ctx, relation, err := tcc.getRelation(dbName, tableName)
  2208  	if err != nil {
  2209  		return nil
  2210  	}
  2211  
  2212  	hideKeys, err := relation.GetHideKeys(ctx)
  2213  	if err != nil {
  2214  		return nil
  2215  	}
  2216  	if len(hideKeys) == 0 {
  2217  		return nil
  2218  	}
  2219  	hideKey := hideKeys[0]
  2220  
  2221  	hideDef := &plan2.ColDef{
  2222  		Name: hideKey.Name,
  2223  		Typ: &plan2.Type{
  2224  			Id:        int32(hideKey.Type.Oid),
  2225  			Width:     hideKey.Type.Width,
  2226  			Precision: hideKey.Type.Precision,
  2227  			Scale:     hideKey.Type.Scale,
  2228  			Size:      hideKey.Type.Size,
  2229  		},
  2230  		Primary: hideKey.Primary,
  2231  	}
  2232  	return hideDef
  2233  }
  2234  
  2235  func fixColumnName(cols []*engine.Attribute, expr *plan.Expr) {
  2236  	switch exprImpl := expr.Expr.(type) {
  2237  	case *plan.Expr_F:
  2238  		for _, arg := range exprImpl.F.Args {
  2239  			fixColumnName(cols, arg)
  2240  		}
  2241  	case *plan.Expr_Col:
  2242  		exprImpl.Col.Name = cols[exprImpl.Col.ColPos].Name
  2243  	}
  2244  }
  2245  
  2246  func (tcc *TxnCompilerContext) Stats(obj *plan2.ObjectRef, e *plan2.Expr) (stats *plan2.Stats) {
  2247  
  2248  	dbName := obj.GetSchemaName()
  2249  	dbName, err := tcc.ensureDatabaseIsNotEmpty(dbName)
  2250  	if err != nil {
  2251  		return
  2252  	}
  2253  	tableName := obj.GetObjName()
  2254  	ctx, table, err := tcc.getRelation(dbName, tableName)
  2255  	if err != nil {
  2256  		return
  2257  	}
  2258  	if e != nil {
  2259  		cols, _ := table.TableColumns(ctx)
  2260  		fixColumnName(cols, e)
  2261  	}
  2262  	stats, _ = table.Stats(ctx, e)
  2263  	return stats
  2264  }
  2265  
  2266  func (tcc *TxnCompilerContext) GetProcess() *process.Process {
  2267  	tcc.mu.Lock()
  2268  	defer tcc.mu.Unlock()
  2269  	return tcc.proc
  2270  }
  2271  
  2272  func (tcc *TxnCompilerContext) GetQueryResultMeta(uuid string) ([]*plan.ColDef, string, error) {
  2273  	proc := tcc.proc
  2274  	// get file size
  2275  	fs := objectio.NewObjectFS(proc.FileService, catalog.QueryResultMetaDir)
  2276  	dirs, err := fs.ListDir(catalog.QueryResultMetaDir)
  2277  	if err != nil {
  2278  		return nil, "", err
  2279  	}
  2280  	var size int64 = -1
  2281  	name := catalog.BuildQueryResultMetaName(proc.SessionInfo.Account, uuid)
  2282  	for _, d := range dirs {
  2283  		if d.Name == name {
  2284  			size = d.Size
  2285  		}
  2286  	}
  2287  	if size == -1 {
  2288  		return nil, "", moerr.NewQueryIdNotFound(proc.Ctx, uuid)
  2289  	}
  2290  	// read meta's meta
  2291  	path := catalog.BuildQueryResultMetaPath(proc.SessionInfo.Account, uuid)
  2292  	reader, err := objectio.NewObjectReader(path, proc.FileService)
  2293  	if err != nil {
  2294  		return nil, "", err
  2295  	}
  2296  	bs, err := reader.ReadAllMeta(proc.Ctx, size, proc.Mp())
  2297  	if err != nil {
  2298  		return nil, "", err
  2299  	}
  2300  	idxs := make([]uint16, 2)
  2301  	idxs[0] = catalog.COLUMNS_IDX
  2302  	idxs[1] = catalog.RESULT_PATH_IDX
  2303  	// read meta's data
  2304  	iov, err := reader.Read(proc.Ctx, bs[0].GetExtent(), idxs, proc.Mp())
  2305  	if err != nil {
  2306  		return nil, "", err
  2307  	}
  2308  	// cols
  2309  	vec := vector.New(catalog.MetaColTypes[catalog.COLUMNS_IDX])
  2310  	if err = vec.Read(iov.Entries[0].Object.([]byte)); err != nil {
  2311  		return nil, "", err
  2312  	}
  2313  	def := vector.MustStrCols(vec)[0]
  2314  	r := &plan.ResultColDef{}
  2315  	if err = r.Unmarshal([]byte(def)); err != nil {
  2316  		return nil, "", err
  2317  	}
  2318  	// paths
  2319  	vec = vector.New(catalog.MetaColTypes[catalog.RESULT_PATH_IDX])
  2320  	if err = vec.Read(iov.Entries[1].Object.([]byte)); err != nil {
  2321  		return nil, "", err
  2322  	}
  2323  	str := vector.MustStrCols(vec)[0]
  2324  	return r.ResultCols, str, nil
  2325  }
  2326  
  2327  func (tcc *TxnCompilerContext) SetProcess(proc *process.Process) {
  2328  	tcc.mu.Lock()
  2329  	defer tcc.mu.Unlock()
  2330  	tcc.proc = proc
  2331  }
  2332  
  2333  // fakeDataSetFetcher gets the result set from the pipeline and save it in the session.
  2334  // It will not send the result to the client.
  2335  func fakeDataSetFetcher(handle interface{}, dataSet *batch.Batch) error {
  2336  	if handle == nil || dataSet == nil {
  2337  		return nil
  2338  	}
  2339  
  2340  	ses := handle.(*Session)
  2341  	oq := newFakeOutputQueue(ses.GetMysqlResultSet())
  2342  	n := vector.Length(dataSet.Vecs[0])
  2343  	for j := 0; j < n; j++ { //row index
  2344  		if dataSet.Zs[j] <= 0 {
  2345  			continue
  2346  		}
  2347  		_, err := extractRowFromEveryVector(ses, dataSet, int64(j), oq)
  2348  		if err != nil {
  2349  			return err
  2350  		}
  2351  	}
  2352  	err := oq.flush()
  2353  	if err != nil {
  2354  		return err
  2355  	}
  2356  	ses.AppendMysqlResultSetOfBackgroundTask(ses.GetMysqlResultSet())
  2357  	return nil
  2358  }
  2359  
  2360  // getResultSet extracts the result set
  2361  func getResultSet(ctx context.Context, bh BackgroundExec) ([]ExecResult, error) {
  2362  	results := bh.GetExecResultSet()
  2363  	rsset := make([]ExecResult, len(results))
  2364  	for i, value := range results {
  2365  		if er, ok := value.(ExecResult); ok {
  2366  			rsset[i] = er
  2367  		} else {
  2368  			return nil, moerr.NewInternalError(ctx, "it is not the type of result set")
  2369  		}
  2370  	}
  2371  	return rsset, nil
  2372  }
  2373  
  2374  // executeSQLInBackgroundSession executes the sql in an independent session and transaction.
  2375  // It sends nothing to the client.
  2376  func executeSQLInBackgroundSession(ctx context.Context, mp *mpool.MPool, pu *config.ParameterUnit, sql string, autoIncrCaches defines.AutoIncrCaches) ([]ExecResult, error) {
  2377  	bh := NewBackgroundHandler(ctx, mp, pu, autoIncrCaches)
  2378  	defer bh.Close()
  2379  	logutil.Debugf("background exec sql:%v", sql)
  2380  	err := bh.Exec(ctx, sql)
  2381  	logutil.Debugf("background exec sql done")
  2382  	if err != nil {
  2383  		return nil, err
  2384  	}
  2385  
  2386  	//get the result set
  2387  	//TODO: debug further
  2388  	//mrsArray := ses.GetAllMysqlResultSet()
  2389  	//for _, mrs := range mrsArray {
  2390  	//	for i := uint64(0); i < mrs.GetRowCount(); i++ {
  2391  	//		row, err := mrs.GetRow(i)
  2392  	//		if err != nil {
  2393  	//			return err
  2394  	//		}
  2395  	//		logutil.Info(row)
  2396  	//	}
  2397  	//}
  2398  
  2399  	return getResultSet(ctx, bh)
  2400  }
  2401  
  2402  type BackgroundHandler struct {
  2403  	mce *MysqlCmdExecutor
  2404  	ses *BackgroundSession
  2405  }
  2406  
  2407  var NewBackgroundHandler = func(ctx context.Context, mp *mpool.MPool, pu *config.ParameterUnit, autoincrcaches defines.AutoIncrCaches) BackgroundExec {
  2408  	bh := &BackgroundHandler{
  2409  		mce: NewMysqlCmdExecutor(),
  2410  		ses: NewBackgroundSession(ctx, mp, pu, GSysVariables, autoincrcaches),
  2411  	}
  2412  	return bh
  2413  }
  2414  
  2415  func (bh *BackgroundHandler) Close() {
  2416  	bh.mce.Close()
  2417  	bh.ses.Close()
  2418  }
  2419  
  2420  func (bh *BackgroundHandler) Exec(ctx context.Context, sql string) error {
  2421  	bh.mce.SetSession(bh.ses.Session)
  2422  	if ctx == nil {
  2423  		ctx = bh.ses.GetRequestContext()
  2424  	} else {
  2425  		bh.ses.SetRequestContext(ctx)
  2426  	}
  2427  	bh.mce.ChooseDoQueryFunc(bh.ses.GetParameterUnit().SV.EnableDoComQueryInProgress)
  2428  	//logutil.Debugf("-->bh:%s", sql)
  2429  	err := bh.mce.GetDoQueryFunc()(ctx, sql)
  2430  	if err != nil {
  2431  		return err
  2432  	}
  2433  	return err
  2434  }
  2435  
  2436  func (bh *BackgroundHandler) GetExecResultSet() []interface{} {
  2437  	mrs := bh.ses.GetAllMysqlResultSet()
  2438  	ret := make([]interface{}, len(mrs))
  2439  	for i, mr := range mrs {
  2440  		ret[i] = mr
  2441  	}
  2442  	return ret
  2443  }
  2444  
  2445  func (bh *BackgroundHandler) ClearExecResultSet() {
  2446  	bh.ses.ClearAllMysqlResultSet()
  2447  }