github.com/matrixorigin/matrixone@v1.2.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  	"sync/atomic"
    25  	"time"
    26  
    27  	"github.com/matrixorigin/matrixone/pkg/logutil"
    28  
    29  	"github.com/google/uuid"
    30  
    31  	"github.com/matrixorigin/matrixone/pkg/bootstrap/versions"
    32  	"github.com/matrixorigin/matrixone/pkg/common/buffer"
    33  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    34  	"github.com/matrixorigin/matrixone/pkg/common/mpool"
    35  	"github.com/matrixorigin/matrixone/pkg/container/batch"
    36  	"github.com/matrixorigin/matrixone/pkg/defines"
    37  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    38  	"github.com/matrixorigin/matrixone/pkg/pb/query"
    39  	"github.com/matrixorigin/matrixone/pkg/pb/status"
    40  	"github.com/matrixorigin/matrixone/pkg/sql/colexec"
    41  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
    42  	plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan"
    43  	"github.com/matrixorigin/matrixone/pkg/util/errutil"
    44  	db_holder "github.com/matrixorigin/matrixone/pkg/util/export/etl/db"
    45  	v2 "github.com/matrixorigin/matrixone/pkg/util/metric/v2"
    46  	"github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace"
    47  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    48  )
    49  
    50  var MaxPrepareNumberInOneSession int = 100000
    51  
    52  // TODO: this variable should be configure by set variable
    53  const MoDefaultErrorCount = 64
    54  
    55  type ShowStatementType int
    56  
    57  const (
    58  	NotShowStatement ShowStatementType = 0
    59  	ShowTableStatus  ShowStatementType = 1
    60  )
    61  
    62  type ConnType int
    63  
    64  const (
    65  	ConnTypeUnset    ConnType = 0
    66  	ConnTypeInternal ConnType = 1
    67  	ConnTypeExternal ConnType = 2
    68  )
    69  
    70  type TS string
    71  
    72  const (
    73  	// Created
    74  	TSCreatedStart TS = "TSCreatedStart"
    75  	TSCreatedEnd   TS = "TSCreatedEnd"
    76  
    77  	// Handler
    78  	TSEstablishStart  TS = "TSEstablishStart"
    79  	TSEstablishEnd    TS = "TSEstablishEnd"
    80  	TSUpgradeTLSStart TS = "TSUpgradeTLSStart"
    81  	TSUpgradeTLSEnd   TS = "TSUpgradeTLSEnd"
    82  
    83  	// mysql protocol
    84  	TSAuthenticateStart  TS = "TSAuthenticateStart"
    85  	TSAuthenticateEnd    TS = "TSAuthenticateEnd"
    86  	TSSendErrPacketStart TS = "TSSendErrPacketStart"
    87  	TSSendErrPacketEnd   TS = "TSSendErrPacketEnd"
    88  	TSSendOKPacketStart  TS = "TSSendOKPacketStart"
    89  	TSSendOKPacketEnd    TS = "TSSendOKPacketEnd"
    90  
    91  	// session
    92  	TSCheckTenantStart      TS = "TSCheckTenantStart"
    93  	TSCheckTenantEnd        TS = "TSCheckTenantEnd"
    94  	TSCheckUserStart        TS = "TSCheckUserStart"
    95  	TSCheckUserEnd          TS = "TSCheckUserEnd"
    96  	TSCheckRoleStart        TS = "TSCheckRoleStart"
    97  	TSCheckRoleEnd          TS = "TSCheckRoleEnd"
    98  	TSCheckDbNameStart      TS = "TSCheckDbNameStart"
    99  	TSCheckDbNameEnd        TS = "TSCheckDbNameEnd"
   100  	TSInitGlobalSysVarStart TS = "TSInitGlobalSysVarStart"
   101  	TSInitGlobalSysVarEnd   TS = "TSInitGlobalSysVarEnd"
   102  )
   103  
   104  type Session struct {
   105  	feSessionImpl
   106  
   107  	//cmd from the client
   108  	cmd CommandType
   109  
   110  	// the process of the session
   111  	proc *process.Process
   112  
   113  	isInternal bool
   114  
   115  	data            [][]interface{}
   116  	ep              *ExportConfig
   117  	showStmtType    ShowStatementType
   118  	sysVars         map[string]interface{}
   119  	userDefinedVars map[string]*UserDefinedVar
   120  
   121  	prepareStmts map[string]*PrepareStmt
   122  	lastStmtId   uint32
   123  
   124  	priv *privilege
   125  
   126  	errInfo *errInfo
   127  
   128  	//fromRealUser distinguish the sql that the user inputs from the one
   129  	//that the internal or background program executes
   130  	fromRealUser bool
   131  
   132  	cache *privilegeCache
   133  
   134  	mu sync.Mutex
   135  
   136  	isNotBackgroundSession bool
   137  	lastInsertID           uint64
   138  	tStmt                  *motrace.StatementInfo
   139  
   140  	ast tree.Statement
   141  
   142  	queryId []string
   143  
   144  	blockIdx int
   145  
   146  	p *plan.Plan
   147  
   148  	limitResultSize float64 // MB
   149  
   150  	curResultSize float64 // MB
   151  
   152  	// sentRows used to record rows it sent to client for motrace.StatementInfo.
   153  	// If there is NO exec_plan, sentRows will be 0.
   154  	sentRows atomic.Int64
   155  	// writeCsvBytes is used to record bytes sent by `select ... into 'file.csv'` for motrace.StatementInfo
   156  	writeCsvBytes atomic.Int64
   157  	// packetCounter count the packet communicated with client.
   158  	packetCounter atomic.Int64
   159  	// payloadCounter count the payload send by `load data`
   160  	payloadCounter int64
   161  
   162  	createdTime time.Time
   163  
   164  	expiredTime time.Time
   165  
   166  	planCache *planCache
   167  
   168  	statsCache   *plan2.StatsCache
   169  	seqCurValues map[uint64]string
   170  
   171  	/*
   172  		CORNER CASE:
   173  
   174  		create sequence seq1;
   175  		set @@a = (select nextval(seq1)); // a = 1
   176  		select currval('seq1');// 1
   177  		select lastval('seq1');// right value is 1
   178  
   179  		We execute the expr of 'set var = expr' in a background session,
   180  		the last value of the seq1 is saved in the background session.
   181  
   182  		If we want to get the right value the lastval('seq1'), we need save
   183  		the last value of the seq1 in the session that starts the background session.
   184  
   185  		So, we define the type of seqLastValue as *string for updating its value conveniently.
   186  
   187  		TODO: we need to reimplement the sequence in some extent traced by issue #9847.
   188  	*/
   189  	seqLastValue *string
   190  
   191  	sqlHelper *SqlHelper
   192  
   193  	rm *RoutineManager
   194  
   195  	rt *Routine
   196  
   197  	// requestLabel is the CN label info requested from client.
   198  	requestLabel map[string]string
   199  	// connTyp indicates the type of connection. Default is ConnTypeUnset.
   200  	// If it is internal connection, the value will be ConnTypeInternal, otherwise,
   201  	// the value will be ConnTypeExternal.
   202  	connType ConnType
   203  
   204  	// startedAt is the session start time.
   205  	startedAt time.Time
   206  
   207  	// queryEnd is the time when the query ends
   208  	queryEnd time.Time
   209  	// queryInProgress indicates whether the query is in progress
   210  	queryInProgress atomic.Bool
   211  	// queryInExecute indicates whether the query is in execute
   212  	queryInExecute atomic.Bool
   213  
   214  	// timestampMap record timestamp for statistical purposes
   215  	timestampMap map[TS]time.Time
   216  
   217  	// insert sql for create table as select stmt
   218  	createAsSelectSql string
   219  
   220  	// FromProxy denotes whether the session is dispatched from proxy
   221  	fromProxy bool
   222  	// If the connection is from proxy, client address is the real address of client.
   223  	clientAddr string
   224  	proxyAddr  string
   225  
   226  	disableTrace bool
   227  }
   228  
   229  func (ses *Session) GetTxnHandler() *TxnHandler {
   230  	ses.mu.Lock()
   231  	defer ses.mu.Unlock()
   232  	return ses.txnHandler
   233  }
   234  
   235  func (ses *Session) GetTenantInfo() *TenantInfo {
   236  	ses.mu.Lock()
   237  	defer ses.mu.Unlock()
   238  	return ses.tenant
   239  }
   240  
   241  func (ses *Session) SendRows() int64 {
   242  	return ses.sentRows.Load()
   243  }
   244  
   245  func (ses *Session) GetStmtInfo() *motrace.StatementInfo {
   246  	return ses.tStmt
   247  }
   248  
   249  func (ses *Session) getNextProcessId() string {
   250  	/*
   251  		temporary method:
   252  		routineId + sqlCount
   253  	*/
   254  	routineId := ses.GetMysqlProtocol().ConnectionID()
   255  	return fmt.Sprintf("%d%d", routineId, ses.GetSqlCount())
   256  }
   257  
   258  func (ses *Session) SetPlan(plan *plan.Plan) {
   259  	ses.p = plan
   260  }
   261  
   262  func (ses *Session) GetProc() *process.Process {
   263  	return ses.proc
   264  }
   265  
   266  func (ses *Session) GetStatsCache() *plan2.StatsCache {
   267  	return ses.statsCache
   268  }
   269  
   270  func (ses *Session) GetSessionStart() time.Time {
   271  	ses.mu.Lock()
   272  	defer ses.mu.Unlock()
   273  	return ses.startedAt
   274  }
   275  
   276  func (ses *Session) SetQueryEnd(t time.Time) {
   277  	ses.mu.Lock()
   278  	defer ses.mu.Unlock()
   279  	ses.queryEnd = t
   280  }
   281  
   282  func (ses *Session) GetQueryEnd() time.Time {
   283  	ses.mu.Lock()
   284  	defer ses.mu.Unlock()
   285  	return ses.queryEnd
   286  }
   287  
   288  func (ses *Session) SetQueryInProgress(b bool) {
   289  	ses.queryInProgress.Store(b)
   290  }
   291  
   292  func (ses *Session) GetQueryInProgress() bool {
   293  	return ses.queryInProgress.Load()
   294  }
   295  
   296  func (ses *Session) SetQueryInExecute(b bool) {
   297  	ses.queryInExecute.Store(b)
   298  }
   299  
   300  func (ses *Session) GetQueryInExecute() bool {
   301  	return ses.queryInExecute.Load()
   302  }
   303  
   304  func (ses *Session) setRoutineManager(rm *RoutineManager) {
   305  	ses.mu.Lock()
   306  	defer ses.mu.Unlock()
   307  	ses.rm = rm
   308  }
   309  
   310  func (ses *Session) getRoutineManager() *RoutineManager {
   311  	ses.mu.Lock()
   312  	defer ses.mu.Unlock()
   313  	return ses.rm
   314  }
   315  
   316  func (ses *Session) setRoutine(rt *Routine) {
   317  	ses.mu.Lock()
   318  	defer ses.mu.Unlock()
   319  	ses.rt = rt
   320  }
   321  
   322  func (ses *Session) getRoutine() *Routine {
   323  	ses.mu.Lock()
   324  	defer ses.mu.Unlock()
   325  	return ses.rt
   326  }
   327  
   328  func (ses *Session) SetSeqLastValue(proc *process.Process) {
   329  	ses.mu.Lock()
   330  	defer ses.mu.Unlock()
   331  	*ses.seqLastValue = proc.SessionInfo.SeqLastValue[0]
   332  }
   333  
   334  func (ses *Session) DeleteSeqValues(proc *process.Process) {
   335  	ses.mu.Lock()
   336  	defer ses.mu.Unlock()
   337  	for _, k := range proc.SessionInfo.SeqDeleteKeys {
   338  		delete(ses.seqCurValues, k)
   339  	}
   340  }
   341  
   342  func (ses *Session) AddSeqValues(proc *process.Process) {
   343  	ses.mu.Lock()
   344  	defer ses.mu.Unlock()
   345  	for k, v := range proc.SessionInfo.SeqAddValues {
   346  		ses.seqCurValues[k] = v
   347  	}
   348  }
   349  
   350  func (ses *Session) GetSeqLastValue() string {
   351  	ses.mu.Lock()
   352  	defer ses.mu.Unlock()
   353  	return *ses.seqLastValue
   354  }
   355  
   356  func (ses *Session) CopySeqToProc(proc *process.Process) {
   357  	ses.mu.Lock()
   358  	defer ses.mu.Unlock()
   359  	for k, v := range ses.seqCurValues {
   360  		proc.SessionInfo.SeqCurValues[k] = v
   361  	}
   362  	proc.SessionInfo.SeqLastValue[0] = *ses.seqLastValue
   363  }
   364  
   365  func (ses *Session) InheritSequenceData(other *Session) {
   366  	ses.mu.Lock()
   367  	defer ses.mu.Unlock()
   368  	ses.seqCurValues = other.seqCurValues
   369  	ses.seqLastValue = other.seqLastValue
   370  }
   371  
   372  func (ses *Session) GetSqlHelper() *SqlHelper {
   373  	ses.mu.Lock()
   374  	defer ses.mu.Unlock()
   375  	return ses.sqlHelper
   376  }
   377  
   378  func (ses *Session) CountPayload(length int) {
   379  	if ses == nil {
   380  		return
   381  	}
   382  	ses.payloadCounter += int64(length)
   383  }
   384  func (ses *Session) CountPacket(delta int64) {
   385  	if ses == nil {
   386  		return
   387  	}
   388  	ses.packetCounter.Add(delta)
   389  }
   390  func (ses *Session) GetPacketCnt() int64 {
   391  	if ses == nil {
   392  		return 0
   393  	}
   394  	return ses.packetCounter.Load()
   395  }
   396  func (ses *Session) ResetPacketCounter() {
   397  	if ses == nil {
   398  		return
   399  	}
   400  	ses.packetCounter.Store(0)
   401  	ses.payloadCounter = 0
   402  }
   403  
   404  // SetTStmt do set the Session.tStmt
   405  // 1. init-set at RecordStatement, which means the statement is started.
   406  // 2. reset at logStatementStringStatus, which means the statement is finished.
   407  func (ses *Session) SetTStmt(stmt *motrace.StatementInfo) {
   408  	ses.mu.Lock()
   409  	defer ses.mu.Unlock()
   410  	ses.tStmt = stmt
   411  }
   412  
   413  const saveQueryIdCnt = 10
   414  
   415  func (ses *Session) pushQueryId(uuid string) {
   416  	if len(ses.queryId) > saveQueryIdCnt {
   417  		ses.queryId = ses.queryId[1:]
   418  	}
   419  	ses.queryId = append(ses.queryId, uuid)
   420  }
   421  
   422  func (ses *Session) getQueryId(internalSql bool) []string {
   423  	if internalSql {
   424  		cnt := len(ses.queryId)
   425  		//the last one is cnt-1
   426  		if cnt > 0 {
   427  			return ses.queryId[:cnt-1]
   428  		} else {
   429  			return ses.queryId[:cnt]
   430  		}
   431  	}
   432  	return ses.queryId
   433  }
   434  
   435  type errInfo struct {
   436  	codes  []uint16
   437  	msgs   []string
   438  	maxCnt int
   439  }
   440  
   441  func (e *errInfo) push(code uint16, msg string) {
   442  	if e.maxCnt > 0 && len(e.codes) > e.maxCnt {
   443  		e.codes = e.codes[1:]
   444  		e.msgs = e.msgs[1:]
   445  	}
   446  	e.codes = append(e.codes, code)
   447  	e.msgs = append(e.msgs, msg)
   448  }
   449  
   450  func (e *errInfo) length() int {
   451  	return len(e.codes)
   452  }
   453  
   454  func NewSession(connCtx context.Context, proto MysqlProtocol, mp *mpool.MPool, gSysVars *GlobalSystemVariables, isNotBackgroundSession bool, sharedTxnHandler *TxnHandler) *Session {
   455  	//if the sharedTxnHandler exists,we use its txnCtx and txnOperator in this session.
   456  	//Currently, we only use the sharedTxnHandler in the background session.
   457  	var txnOp TxnOperator
   458  	var err error
   459  	if sharedTxnHandler != nil {
   460  		if !sharedTxnHandler.InActiveTxn() {
   461  			panic("shared txn is invalid")
   462  		}
   463  		txnOp = sharedTxnHandler.GetTxn()
   464  	}
   465  	txnHandler := InitTxnHandler(getGlobalPu().StorageEngine, connCtx, txnOp)
   466  
   467  	ses := &Session{
   468  		feSessionImpl: feSessionImpl{
   469  			proto:      proto,
   470  			pool:       mp,
   471  			txnHandler: txnHandler,
   472  			//TODO:fix database name after the catalog is ready
   473  			txnCompileCtx:  InitTxnCompilerContext(proto.GetDatabaseName()),
   474  			gSysVars:       gSysVars,
   475  			outputCallback: getDataFromPipeline,
   476  			timeZone:       time.Local,
   477  		},
   478  		errInfo: &errInfo{
   479  			codes:  make([]uint16, 0, MoDefaultErrorCount),
   480  			msgs:   make([]string, 0, MoDefaultErrorCount),
   481  			maxCnt: MoDefaultErrorCount,
   482  		},
   483  		cache:     &privilegeCache{},
   484  		blockIdx:  0,
   485  		planCache: newPlanCache(100),
   486  		startedAt: time.Now(),
   487  		connType:  ConnTypeUnset,
   488  
   489  		timestampMap: map[TS]time.Time{},
   490  		statsCache:   plan2.NewStatsCache(),
   491  	}
   492  	if isNotBackgroundSession {
   493  		ses.sysVars = gSysVars.CopySysVarsToSession()
   494  		ses.userDefinedVars = make(map[string]*UserDefinedVar)
   495  		ses.prepareStmts = make(map[string]*PrepareStmt)
   496  		// For seq init values.
   497  		ses.seqCurValues = make(map[uint64]string)
   498  		ses.seqLastValue = new(string)
   499  	}
   500  
   501  	ses.buf = buffer.New()
   502  	ses.isNotBackgroundSession = isNotBackgroundSession
   503  	ses.sqlHelper = &SqlHelper{ses: ses}
   504  	ses.uuid, _ = uuid.NewV7()
   505  	if ses.pool == nil {
   506  		// If no mp, we create one for session.  Use GuestMmuLimitation as cap.
   507  		// fixed pool size can be another param, or should be computed from cap,
   508  		// but here, too lazy, just use Mid.
   509  		//
   510  		// XXX MPOOL
   511  		// We don't have a way to close a session, so the only sane way of creating
   512  		// a mpool is to use NoFixed
   513  		ses.pool, err = mpool.NewMPool("pipeline-"+ses.GetUUIDString(), getGlobalPu().SV.GuestMmuLimitation, mpool.NoFixed)
   514  		if err != nil {
   515  			panic(err)
   516  		}
   517  	}
   518  	ses.proc = process.New(
   519  		context.TODO(),
   520  		ses.pool,
   521  		getGlobalPu().TxnClient,
   522  		nil,
   523  		getGlobalPu().FileService,
   524  		getGlobalPu().LockService,
   525  		getGlobalPu().QueryClient,
   526  		getGlobalPu().HAKeeperClient,
   527  		getGlobalPu().UdfService,
   528  		getGlobalAic())
   529  
   530  	ses.proc.Lim.Size = getGlobalPu().SV.ProcessLimitationSize
   531  	ses.proc.Lim.BatchRows = getGlobalPu().SV.ProcessLimitationBatchRows
   532  	ses.proc.Lim.MaxMsgSize = getGlobalPu().SV.MaxMessageSize
   533  	ses.proc.Lim.PartitionRows = getGlobalPu().SV.ProcessLimitationPartitionRows
   534  
   535  	ses.proc.SetStmtProfile(&ses.stmtProfile)
   536  	// ses.proc.SetResolveVariableFunc(ses.txnCompileCtx.ResolveVariable)
   537  
   538  	runtime.SetFinalizer(ses, func(ss *Session) {
   539  		ss.Close()
   540  	})
   541  	return ses
   542  }
   543  
   544  func (ses *Session) Close() {
   545  	ses.mu.Lock()
   546  	defer ses.mu.Unlock()
   547  	ses.feSessionImpl.Close()
   548  	ses.feSessionImpl.Clear()
   549  	ses.proto = nil
   550  	ses.mrs = nil
   551  	ses.data = nil
   552  	ses.ep = nil
   553  	if ses.txnHandler != nil {
   554  		ses.txnHandler.Close()
   555  		ses.txnHandler = nil
   556  	}
   557  	if ses.txnCompileCtx != nil {
   558  		ses.txnCompileCtx.execCtx = nil
   559  		ses.txnCompileCtx = nil
   560  	}
   561  	ses.sql = ""
   562  	ses.sysVars = nil
   563  	ses.userDefinedVars = nil
   564  	ses.gSysVars = nil
   565  	for _, stmt := range ses.prepareStmts {
   566  		stmt.Close()
   567  	}
   568  	ses.prepareStmts = nil
   569  	ses.allResultSet = nil
   570  	ses.tenant = nil
   571  	ses.priv = nil
   572  	ses.errInfo = nil
   573  	ses.cache = nil
   574  	ses.debugStr = ""
   575  	ses.tStmt = nil
   576  	ses.ast = nil
   577  	ses.rs = nil
   578  	ses.queryId = nil
   579  	ses.p = nil
   580  	ses.planCache = nil
   581  	ses.seqCurValues = nil
   582  	ses.seqLastValue = nil
   583  	if ses.sqlHelper != nil {
   584  		ses.sqlHelper.ses = nil
   585  		ses.sqlHelper = nil
   586  	}
   587  	ses.ClearStmtProfile()
   588  	//  The mpool cleanup must be placed at the end,
   589  	// and you must wait for all resources to be cleaned up before you can delete the mpool
   590  	if ses.proc != nil {
   591  		ses.proc.FreeVectors()
   592  		bats := ses.proc.GetValueScanBatchs()
   593  		for _, bat := range bats {
   594  			bat.Clean(ses.proc.Mp())
   595  		}
   596  		ses.proc = nil
   597  	}
   598  	for _, bat := range ses.resultBatches {
   599  		bat.Clean(ses.pool)
   600  	}
   601  	if ses.isNotBackgroundSession {
   602  		pool := ses.GetMemPool()
   603  		mpool.DeleteMPool(pool)
   604  		ses.SetMemPool(nil)
   605  	}
   606  	if ses.buf != nil {
   607  		ses.buf.Free()
   608  		ses.buf = nil
   609  	}
   610  
   611  	ses.timestampMap = nil
   612  	ses.upstream = nil
   613  	ses.rm = nil
   614  	ses.rt = nil
   615  }
   616  
   617  func (ses *Session) Clear() {
   618  	ses.feSessionImpl.Clear()
   619  }
   620  
   621  func (ses *Session) GetIncBlockIdx() int {
   622  	ses.blockIdx++
   623  	return ses.blockIdx
   624  }
   625  
   626  func (ses *Session) ResetBlockIdx() {
   627  	ses.blockIdx = 0
   628  }
   629  
   630  func (ses *Session) IsBackgroundSession() bool {
   631  	ses.mu.Lock()
   632  	defer ses.mu.Unlock()
   633  	return !ses.isNotBackgroundSession
   634  }
   635  
   636  func (ses *Session) cachePlan(sql string, stmts []tree.Statement, plans []*plan.Plan) {
   637  	if len(sql) == 0 {
   638  		return
   639  	}
   640  	ses.mu.Lock()
   641  	defer ses.mu.Unlock()
   642  	ses.planCache.cache(sql, stmts, plans)
   643  }
   644  
   645  func (ses *Session) getCachedPlan(sql string) *cachedPlan {
   646  	if len(sql) == 0 {
   647  		return nil
   648  	}
   649  	ses.mu.Lock()
   650  	defer ses.mu.Unlock()
   651  	return ses.planCache.get(sql)
   652  }
   653  
   654  func (ses *Session) isCached(sql string) bool {
   655  	if len(sql) == 0 {
   656  		return false
   657  	}
   658  	ses.mu.Lock()
   659  	defer ses.mu.Unlock()
   660  	return ses.planCache.isCached(sql)
   661  }
   662  
   663  func (ses *Session) cleanCache() {
   664  	ses.mu.Lock()
   665  	defer ses.mu.Unlock()
   666  	ses.planCache.clean()
   667  }
   668  
   669  func (ses *Session) UpdateDebugString() {
   670  	ses.mu.Lock()
   671  	defer ses.mu.Unlock()
   672  	sb := bytes.Buffer{}
   673  	//option connection id , ip
   674  	if ses.proto != nil {
   675  		sb.WriteString(fmt.Sprintf("connectionId %d", ses.proto.ConnectionID()))
   676  		sb.WriteByte('|')
   677  		sb.WriteString(ses.proto.Peer())
   678  	}
   679  	sb.WriteByte('|')
   680  	//account info
   681  	if ses.tenant != nil {
   682  		sb.WriteString(ses.tenant.String())
   683  	} else {
   684  		acc := getDefaultAccount()
   685  		sb.WriteString(acc.String())
   686  	}
   687  	sb.WriteByte('|')
   688  	//go routine id
   689  	if ses.rt != nil {
   690  		sb.WriteString(fmt.Sprintf("goRoutineId %d", ses.rt.getGoroutineId()))
   691  		sb.WriteByte('|')
   692  	}
   693  	//session id
   694  	sb.WriteString(ses.uuid.String())
   695  	//upstream sessionid
   696  	if ses.upstream != nil {
   697  		sb.WriteByte('|')
   698  		sb.WriteString(ses.upstream.uuid.String())
   699  	}
   700  
   701  	ses.debugStr = sb.String()
   702  }
   703  
   704  func (ses *Session) GetPrivilegeCache() *privilegeCache {
   705  	ses.mu.Lock()
   706  	defer ses.mu.Unlock()
   707  	return ses.cache
   708  }
   709  
   710  func (ses *Session) InvalidatePrivilegeCache() {
   711  	ses.mu.Lock()
   712  	defer ses.mu.Unlock()
   713  	ses.cache.invalidate()
   714  }
   715  
   716  // GetBackgroundExec generates a background executor
   717  func (ses *Session) GetBackgroundExec(ctx context.Context) BackgroundExec {
   718  	return NewBackgroundExec(
   719  		ctx,
   720  		ses,
   721  		ses.GetMemPool())
   722  }
   723  
   724  // GetShareTxnBackgroundExec returns a background executor running the sql in a shared transaction.
   725  // newRawBatch denotes we need the raw batch instead of mysql result set.
   726  func (ses *Session) GetShareTxnBackgroundExec(ctx context.Context, newRawBatch bool) BackgroundExec {
   727  	var txnOp TxnOperator
   728  	if ses.GetTxnHandler() != nil {
   729  		txnOp = ses.GetTxnHandler().GetTxn()
   730  	}
   731  
   732  	txnHandler := InitTxnHandler(getGlobalPu().StorageEngine, ses.GetTxnHandler().GetConnCtx(), txnOp)
   733  	var callback outputCallBackFunc
   734  	if newRawBatch {
   735  		callback = batchFetcher2
   736  	} else {
   737  		callback = fakeDataSetFetcher2
   738  	}
   739  	backSes := &backSession{
   740  		feSessionImpl: feSessionImpl{
   741  			pool:           ses.pool,
   742  			proto:          &FakeProtocol{},
   743  			buf:            buffer.New(),
   744  			stmtProfile:    process.StmtProfile{},
   745  			tenant:         nil,
   746  			txnHandler:     txnHandler,
   747  			txnCompileCtx:  InitTxnCompilerContext(ses.proto.GetDatabaseName()),
   748  			mrs:            nil,
   749  			outputCallback: callback,
   750  			allResultSet:   nil,
   751  			resultBatches:  nil,
   752  			derivedStmt:    false,
   753  			gSysVars:       GSysVariables,
   754  			label:          make(map[string]string),
   755  			timeZone:       time.Local,
   756  		},
   757  	}
   758  	backSes.uuid, _ = uuid.NewV7()
   759  	bh := &backExec{
   760  		backSes: backSes,
   761  	}
   762  	//the derived statement execute in a shared transaction in background session
   763  	bh.backSes.ReplaceDerivedStmt(true)
   764  	return bh
   765  }
   766  
   767  var GetRawBatchBackgroundExec = func(ctx context.Context, ses *Session) BackgroundExec {
   768  	return ses.GetRawBatchBackgroundExec(ctx)
   769  }
   770  
   771  func (ses *Session) GetRawBatchBackgroundExec(ctx context.Context) BackgroundExec {
   772  	txnHandler := InitTxnHandler(getGlobalPu().StorageEngine, ses.GetTxnHandler().GetConnCtx(), nil)
   773  	backSes := &backSession{
   774  		feSessionImpl: feSessionImpl{
   775  			pool:           ses.GetMemPool(),
   776  			proto:          &FakeProtocol{},
   777  			buf:            buffer.New(),
   778  			stmtProfile:    process.StmtProfile{},
   779  			tenant:         nil,
   780  			txnHandler:     txnHandler,
   781  			txnCompileCtx:  InitTxnCompilerContext(""),
   782  			mrs:            nil,
   783  			outputCallback: batchFetcher2,
   784  			allResultSet:   nil,
   785  			resultBatches:  nil,
   786  			derivedStmt:    false,
   787  			gSysVars:       GSysVariables,
   788  			label:          make(map[string]string),
   789  			timeZone:       time.Local,
   790  		},
   791  	}
   792  	backSes.uuid, _ = uuid.NewV7()
   793  	bh := &backExec{
   794  		backSes: backSes,
   795  	}
   796  	return bh
   797  }
   798  
   799  func (ses *Session) GetIsInternal() bool {
   800  	ses.mu.Lock()
   801  	defer ses.mu.Unlock()
   802  	return ses.isInternal
   803  }
   804  
   805  func (ses *Session) GetData() [][]interface{} {
   806  	ses.mu.Lock()
   807  	defer ses.mu.Unlock()
   808  	return ses.data
   809  }
   810  
   811  func (ses *Session) SetData(data [][]interface{}) {
   812  	ses.mu.Lock()
   813  	defer ses.mu.Unlock()
   814  	ses.data = data
   815  }
   816  
   817  func (ses *Session) AppendData(row []interface{}) {
   818  	ses.mu.Lock()
   819  	defer ses.mu.Unlock()
   820  	ses.data = append(ses.data, row)
   821  }
   822  
   823  func (ses *Session) InitExportConfig(ep *tree.ExportParam) {
   824  	ses.mu.Lock()
   825  	defer ses.mu.Unlock()
   826  	ses.ep = &ExportConfig{userConfig: ep}
   827  }
   828  
   829  func (ses *Session) GetExportConfig() *ExportConfig {
   830  	ses.mu.Lock()
   831  	defer ses.mu.Unlock()
   832  	return ses.ep
   833  }
   834  
   835  func (ses *Session) ClearExportParam() {
   836  	ses.mu.Lock()
   837  	defer ses.mu.Unlock()
   838  	ses.ep = nil
   839  }
   840  
   841  func (ses *Session) SetShowStmtType(sst ShowStatementType) {
   842  	ses.mu.Lock()
   843  	defer ses.mu.Unlock()
   844  	ses.showStmtType = sst
   845  }
   846  
   847  func (ses *Session) GetShowStmtType() ShowStatementType {
   848  	ses.mu.Lock()
   849  	defer ses.mu.Unlock()
   850  	return ses.showStmtType
   851  }
   852  
   853  func (ses *Session) GetOutputCallback(execCtx *ExecCtx) func(*batch.Batch) error {
   854  	ses.mu.Lock()
   855  	defer ses.mu.Unlock()
   856  	return func(bat *batch.Batch) error {
   857  		return ses.outputCallback(ses, execCtx, bat)
   858  	}
   859  }
   860  
   861  func (ses *Session) GetErrInfo() *errInfo {
   862  	ses.mu.Lock()
   863  	defer ses.mu.Unlock()
   864  	return ses.errInfo
   865  }
   866  
   867  func (ses *Session) GenNewStmtId() uint32 {
   868  	ses.mu.Lock()
   869  	defer ses.mu.Unlock()
   870  	ses.lastStmtId = ses.lastStmtId + 1
   871  	return ses.lastStmtId
   872  }
   873  
   874  func (ses *Session) SetLastStmtID(id uint32) {
   875  	ses.mu.Lock()
   876  	defer ses.mu.Unlock()
   877  	ses.lastStmtId = id
   878  }
   879  
   880  func (ses *Session) GetLastStmtId() uint32 {
   881  	ses.mu.Lock()
   882  	defer ses.mu.Unlock()
   883  	return ses.lastStmtId
   884  }
   885  
   886  func (ses *Session) SetLastInsertID(num uint64) {
   887  	ses.mu.Lock()
   888  	defer ses.mu.Unlock()
   889  	ses.lastInsertID = num
   890  }
   891  
   892  func (ses *Session) GetLastInsertID() uint64 {
   893  	ses.mu.Lock()
   894  	defer ses.mu.Unlock()
   895  	return ses.lastInsertID
   896  }
   897  
   898  func (ses *Session) SetCmd(cmd CommandType) {
   899  	ses.mu.Lock()
   900  	defer ses.mu.Unlock()
   901  	ses.cmd = cmd
   902  }
   903  
   904  func (ses *Session) GetCmd() CommandType {
   905  	ses.mu.Lock()
   906  	defer ses.mu.Unlock()
   907  	return ses.cmd
   908  }
   909  
   910  // GetTenantName return tenant name according to GetTenantInfo and stmt.
   911  //
   912  // With stmt = nil, should be only called in TxnHandler.NewTxn, TxnHandler.CommitTxn, TxnHandler.RollbackTxn
   913  func (ses *Session) GetTenantNameWithStmt(stmt tree.Statement) string {
   914  	tenant := sysAccountName
   915  	if ses.GetTenantInfo() != nil && (stmt == nil || !IsPrepareStatement(stmt)) {
   916  		tenant = ses.GetTenantInfo().GetTenant()
   917  	}
   918  	return tenant
   919  }
   920  
   921  func (ses *Session) GetTenantName() string {
   922  	return ses.GetTenantNameWithStmt(nil)
   923  }
   924  
   925  func (ses *Session) SetPrepareStmt(ctx context.Context, name string, prepareStmt *PrepareStmt) error {
   926  	ses.mu.Lock()
   927  	defer ses.mu.Unlock()
   928  	if stmt, ok := ses.prepareStmts[name]; !ok {
   929  		if len(ses.prepareStmts) >= MaxPrepareNumberInOneSession {
   930  			return moerr.NewInvalidState(ctx, "too many prepared statement, max %d", MaxPrepareNumberInOneSession)
   931  		}
   932  	} else {
   933  		stmt.Close()
   934  	}
   935  	if prepareStmt != nil && prepareStmt.PreparePlan != nil {
   936  		isInsertValues, exprList := checkPlanIsInsertValues(ses.proc,
   937  			prepareStmt.PreparePlan.GetDcl().GetPrepare().GetPlan())
   938  		if isInsertValues {
   939  			prepareStmt.proc = ses.proc
   940  			prepareStmt.exprList = exprList
   941  		}
   942  	}
   943  	ses.prepareStmts[name] = prepareStmt
   944  
   945  	return nil
   946  }
   947  
   948  func (ses *Session) GetPrepareStmt(ctx context.Context, name string) (*PrepareStmt, error) {
   949  	ses.mu.Lock()
   950  	defer ses.mu.Unlock()
   951  	if prepareStmt, ok := ses.prepareStmts[name]; ok {
   952  		return prepareStmt, nil
   953  	}
   954  	var connID uint32
   955  	if ses.proto != nil {
   956  		connID = ses.proto.ConnectionID()
   957  	}
   958  	logutil.Errorf("prepared statement '%s' does not exist on connection %d", name, connID)
   959  	return nil, moerr.NewInvalidState(ctx, "prepared statement '%s' does not exist", name)
   960  }
   961  
   962  func (ses *Session) GetPrepareStmts() []*PrepareStmt {
   963  	ses.mu.Lock()
   964  	defer ses.mu.Unlock()
   965  	ret := make([]*PrepareStmt, 0, len(ses.prepareStmts))
   966  	for _, st := range ses.prepareStmts {
   967  		ret = append(ret, st)
   968  	}
   969  	return ret
   970  }
   971  
   972  func (ses *Session) RemovePrepareStmt(name string) {
   973  	ses.mu.Lock()
   974  	defer ses.mu.Unlock()
   975  	if stmt, ok := ses.prepareStmts[name]; ok {
   976  		stmt.Close()
   977  	}
   978  	delete(ses.prepareStmts, name)
   979  }
   980  
   981  func (ses *Session) SetSysVar(name string, value interface{}) {
   982  	ses.mu.Lock()
   983  	defer ses.mu.Unlock()
   984  	ses.sysVars[name] = value
   985  }
   986  
   987  func (ses *Session) GetSysVar(name string) interface{} {
   988  	ses.mu.Lock()
   989  	defer ses.mu.Unlock()
   990  	return ses.sysVars[name]
   991  }
   992  
   993  func (ses *Session) GetSysVars() map[string]interface{} {
   994  	ses.mu.Lock()
   995  	defer ses.mu.Unlock()
   996  	return ses.sysVars
   997  }
   998  
   999  // SetGlobalVar sets the value of system variable in global.
  1000  // used by SET GLOBAL
  1001  func (ses *Session) SetGlobalVar(ctx context.Context, name string, value interface{}) error {
  1002  	return ses.GetGlobalSysVars().SetGlobalSysVar(ctx, name, value)
  1003  }
  1004  
  1005  // GetGlobalVar gets this value of the system variable in global
  1006  func (ses *Session) GetGlobalVar(ctx context.Context, name string) (interface{}, error) {
  1007  	gSysVars := ses.GetGlobalSysVars()
  1008  	if def, val, ok := gSysVars.GetGlobalSysVar(name); ok {
  1009  		if def.GetScope() == ScopeSession {
  1010  			//empty
  1011  			return nil, moerr.NewInternalError(ctx, errorSystemVariableSessionEmpty())
  1012  		}
  1013  		return val, nil
  1014  	}
  1015  	return nil, moerr.NewInternalError(ctx, errorSystemVariableDoesNotExist())
  1016  }
  1017  
  1018  // SetSessionVar sets the value of system variable in session
  1019  func (ses *Session) SetSessionVar(ctx context.Context, name string, value interface{}) error {
  1020  	gSysVars := ses.GetGlobalSysVars()
  1021  	if def, _, ok := gSysVars.GetGlobalSysVar(name); ok {
  1022  		if def.GetScope() == ScopeGlobal {
  1023  			return moerr.NewInternalError(ctx, errorSystemVariableIsGlobal())
  1024  		}
  1025  		//scope session & both
  1026  		if !def.GetDynamic() {
  1027  			return moerr.NewInternalError(ctx, errorSystemVariableIsReadOnly())
  1028  		}
  1029  
  1030  		cv, err := def.GetType().Convert(value)
  1031  		if err != nil {
  1032  			errutil.ReportError(ctx, err)
  1033  			return err
  1034  		}
  1035  
  1036  		if def.UpdateSessVar == nil {
  1037  			ses.SetSysVar(def.GetName(), cv)
  1038  		} else {
  1039  			return def.UpdateSessVar(ctx, ses, ses.GetSysVars(), def.GetName(), cv)
  1040  		}
  1041  	} else {
  1042  		return moerr.NewInternalError(ctx, errorSystemVariableDoesNotExist())
  1043  	}
  1044  	return nil
  1045  }
  1046  
  1047  // InitSetSessionVar sets the value of system variable in session when start a connection
  1048  func (ses *Session) InitSetSessionVar(ctx context.Context, name string, value interface{}) error {
  1049  	gSysVars := ses.GetGlobalSysVars()
  1050  	if def, _, ok := gSysVars.GetGlobalSysVar(name); ok {
  1051  		cv, err := def.GetType().Convert(value)
  1052  		if err != nil {
  1053  			errutil.ReportError(ctx, moerr.NewInternalError(context.Background(), "init variable fail: variable %s convert to the system variable type %s failed, bad value %v", name, def.GetType().String(), value))
  1054  		}
  1055  
  1056  		if def.UpdateSessVar == nil {
  1057  			ses.SetSysVar(def.GetName(), cv)
  1058  		} else {
  1059  			return def.UpdateSessVar(ctx, ses, ses.GetSysVars(), def.GetName(), cv)
  1060  		}
  1061  	}
  1062  	return nil
  1063  }
  1064  
  1065  // GetSessionVar gets this value of the system variable in session
  1066  func (ses *Session) GetSessionVar(ctx context.Context, name string) (interface{}, error) {
  1067  	gSysVars := ses.GetGlobalSysVars()
  1068  	if def, gVal, ok := gSysVars.GetGlobalSysVar(name); ok {
  1069  		ciname := strings.ToLower(name)
  1070  		if def.GetScope() == ScopeGlobal {
  1071  			return gVal, nil
  1072  		}
  1073  		return ses.GetSysVar(ciname), nil
  1074  	} else {
  1075  		return nil, moerr.NewInternalError(ctx, errorSystemVariableDoesNotExist())
  1076  	}
  1077  }
  1078  
  1079  func (ses *Session) CopyAllSessionVars() map[string]interface{} {
  1080  	ses.mu.Lock()
  1081  	defer ses.mu.Unlock()
  1082  	cp := make(map[string]interface{})
  1083  	for k, v := range ses.sysVars {
  1084  		cp[k] = v
  1085  	}
  1086  	return cp
  1087  }
  1088  
  1089  // SetUserDefinedVar sets the user defined variable to the value in session
  1090  func (ses *Session) SetUserDefinedVar(name string, value interface{}, sql string) error {
  1091  	ses.mu.Lock()
  1092  	defer ses.mu.Unlock()
  1093  	ses.userDefinedVars[strings.ToLower(name)] = &UserDefinedVar{Value: value, Sql: sql}
  1094  	return nil
  1095  }
  1096  
  1097  // GetUserDefinedVar gets value of the user defined variable
  1098  func (ses *Session) GetUserDefinedVar(name string) (SystemVariableType, *UserDefinedVar, error) {
  1099  	ses.mu.Lock()
  1100  	defer ses.mu.Unlock()
  1101  	val, ok := ses.userDefinedVars[strings.ToLower(name)]
  1102  	if !ok {
  1103  		return SystemVariableNullType{}, nil, nil
  1104  	}
  1105  	return InitSystemVariableStringType(name), val, nil
  1106  }
  1107  
  1108  func (ses *Session) GetTxnInfo() string {
  1109  	txnH := ses.GetTxnHandler()
  1110  	if txnH == nil {
  1111  		return ""
  1112  	}
  1113  	txnOp := txnH.GetTxn()
  1114  	if txnOp == nil {
  1115  		return ""
  1116  	}
  1117  	meta := txnOp.Txn()
  1118  	return meta.DebugString()
  1119  }
  1120  
  1121  func (ses *Session) GetDatabaseName() string {
  1122  	return ses.GetMysqlProtocol().GetDatabaseName()
  1123  }
  1124  
  1125  func (ses *Session) SetDatabaseName(db string) {
  1126  	ses.GetMysqlProtocol().SetDatabaseName(db)
  1127  	ses.GetTxnCompileCtx().SetDatabase(db)
  1128  }
  1129  
  1130  func (ses *Session) DatabaseNameIsEmpty() bool {
  1131  	return len(ses.GetDatabaseName()) == 0
  1132  }
  1133  
  1134  func (ses *Session) SetUserName(uname string) {
  1135  	ses.GetMysqlProtocol().SetUserName(uname)
  1136  }
  1137  
  1138  func (ses *Session) GetConnectionID() uint32 {
  1139  	protocol := ses.GetMysqlProtocol()
  1140  	if protocol != nil {
  1141  		return ses.GetMysqlProtocol().ConnectionID()
  1142  	}
  1143  	return 0
  1144  }
  1145  
  1146  func (ses *Session) skipAuthForSpecialUser() bool {
  1147  	if ses.GetTenantInfo() != nil {
  1148  		ok, _, _ := isSpecialUser(ses.GetTenantInfo().GetUser())
  1149  		return ok
  1150  	}
  1151  	return false
  1152  }
  1153  
  1154  // AuthenticateUser Verify the user's password, and if the login information contains the database name, verify if the database exists
  1155  func (ses *Session) AuthenticateUser(ctx context.Context, userInput string, dbName string, authResponse []byte, salt []byte, checkPassword func(pwd []byte, salt []byte, auth []byte) bool) ([]byte, error) {
  1156  	var defaultRoleID int64
  1157  	var defaultRole string
  1158  	var tenant *TenantInfo
  1159  	var err error
  1160  	var rsset []ExecResult
  1161  	var tenantID int64
  1162  	var userID int64
  1163  	var pwd, accountStatus string
  1164  	var accountVersion uint64
  1165  	//var createVersion string
  1166  	var pwdBytes []byte
  1167  	var isSpecial bool
  1168  	var specialAccount *TenantInfo
  1169  
  1170  	//Get tenant info
  1171  	tenant, err = GetTenantInfo(ctx, userInput)
  1172  	if err != nil {
  1173  		return nil, err
  1174  	}
  1175  
  1176  	ses.SetTenantInfo(tenant)
  1177  	ses.UpdateDebugString()
  1178  	sessionInfo := ses.GetDebugString()
  1179  
  1180  	logDebugf(sessionInfo, "check special user")
  1181  	// check the special user for initilization
  1182  	isSpecial, pwdBytes, specialAccount = isSpecialUser(tenant.GetUser())
  1183  	if isSpecial && specialAccount.IsMoAdminRole() {
  1184  		ses.SetTenantInfo(specialAccount)
  1185  		if len(ses.requestLabel) == 0 {
  1186  			ses.requestLabel = db_holder.GetLabelSelector()
  1187  		}
  1188  		return GetPassWord(HashPassWordWithByte(pwdBytes))
  1189  	}
  1190  
  1191  	ses.SetTenantInfo(tenant)
  1192  
  1193  	//step1 : check tenant exists or not in SYS tenant context
  1194  	ses.timestampMap[TSCheckTenantStart] = time.Now()
  1195  	sysTenantCtx := defines.AttachAccount(ctx, uint32(sysAccountID), uint32(rootID), uint32(moAdminRoleID))
  1196  	sqlForCheckTenant, err := getSqlForCheckTenant(sysTenantCtx, tenant.GetTenant())
  1197  	if err != nil {
  1198  		return nil, err
  1199  	}
  1200  	mp := ses.GetMemPool()
  1201  	logDebugf(sessionInfo, "check tenant %s exists", tenant)
  1202  	rsset, err = executeSQLInBackgroundSession(sysTenantCtx, ses, mp, sqlForCheckTenant)
  1203  	if err != nil {
  1204  		return nil, err
  1205  	}
  1206  	if !execResultArrayHasData(rsset) {
  1207  		return nil, moerr.NewInternalError(sysTenantCtx, "there is no tenant %s", tenant.GetTenant())
  1208  	}
  1209  
  1210  	//account id
  1211  	tenantID, err = rsset[0].GetInt64(sysTenantCtx, 0, 0)
  1212  	if err != nil {
  1213  		return nil, err
  1214  	}
  1215  
  1216  	//account status
  1217  	accountStatus, err = rsset[0].GetString(sysTenantCtx, 0, 2)
  1218  	if err != nil {
  1219  		return nil, err
  1220  	}
  1221  
  1222  	//account version
  1223  	accountVersion, err = rsset[0].GetUint64(sysTenantCtx, 0, 3)
  1224  	if err != nil {
  1225  		return nil, err
  1226  	}
  1227  
  1228  	if strings.ToLower(accountStatus) == tree.AccountStatusSuspend.String() {
  1229  		return nil, moerr.NewInternalError(sysTenantCtx, "Account %s is suspended", tenant.GetTenant())
  1230  	}
  1231  
  1232  	if strings.ToLower(accountStatus) == tree.AccountStatusRestricted.String() {
  1233  		ses.getRoutine().setResricted(true)
  1234  	} else {
  1235  		ses.getRoutine().setResricted(false)
  1236  	}
  1237  
  1238  	tenant.SetTenantID(uint32(tenantID))
  1239  	ses.timestampMap[TSCheckTenantEnd] = time.Now()
  1240  	v2.CheckTenantDurationHistogram.Observe(ses.timestampMap[TSCheckTenantEnd].Sub(ses.timestampMap[TSCheckTenantStart]).Seconds())
  1241  
  1242  	//step2 : check user exists or not in general tenant.
  1243  	//step3 : get the password of the user
  1244  
  1245  	ses.timestampMap[TSCheckUserStart] = time.Now()
  1246  	tenantCtx := defines.AttachAccountId(ctx, uint32(tenantID))
  1247  
  1248  	logDebugf(sessionInfo, "check user of %s exists", tenant)
  1249  	//Get the password of the user in an independent session
  1250  	sqlForPasswordOfUser, err := getSqlForPasswordOfUser(tenantCtx, tenant.GetUser())
  1251  	if err != nil {
  1252  		return nil, err
  1253  	}
  1254  	rsset, err = executeSQLInBackgroundSession(tenantCtx, ses, mp, sqlForPasswordOfUser)
  1255  	if err != nil {
  1256  		return nil, err
  1257  	}
  1258  	if !execResultArrayHasData(rsset) {
  1259  		return nil, moerr.NewInternalError(tenantCtx, "there is no user %s", tenant.GetUser())
  1260  	}
  1261  
  1262  	userID, err = rsset[0].GetInt64(tenantCtx, 0, 0)
  1263  	if err != nil {
  1264  		return nil, err
  1265  	}
  1266  
  1267  	pwd, err = rsset[0].GetString(tenantCtx, 0, 1)
  1268  	if err != nil {
  1269  		return nil, err
  1270  	}
  1271  
  1272  	//the default_role in the mo_user table.
  1273  	//the default_role is always valid. public or other valid role.
  1274  	defaultRoleID, err = rsset[0].GetInt64(tenantCtx, 0, 2)
  1275  	if err != nil {
  1276  		return nil, err
  1277  	}
  1278  
  1279  	tenant.SetUserID(uint32(userID))
  1280  	tenant.SetDefaultRoleID(uint32(defaultRoleID))
  1281  	ses.timestampMap[TSCheckUserEnd] = time.Now()
  1282  	v2.CheckUserDurationHistogram.Observe(ses.timestampMap[TSCheckUserEnd].Sub(ses.timestampMap[TSCheckUserStart]).Seconds())
  1283  
  1284  	/*
  1285  		login case 1: tenant:user
  1286  		1.get the default_role of the user in mo_user
  1287  
  1288  		login case 2: tenant:user:role
  1289  		1.check the role has been granted to the user
  1290  			-yes: go on
  1291  			-no: error
  1292  
  1293  	*/
  1294  	//it denotes that there is no default role in the input
  1295  	if tenant.HasDefaultRole() {
  1296  		logDebugf(sessionInfo, "check default role of user %s.", tenant)
  1297  		//step4 : check role exists or not
  1298  		ses.timestampMap[TSCheckRoleStart] = time.Now()
  1299  		sqlForCheckRoleExists, err := getSqlForRoleIdOfRole(tenantCtx, tenant.GetDefaultRole())
  1300  		if err != nil {
  1301  			return nil, err
  1302  		}
  1303  		rsset, err = executeSQLInBackgroundSession(tenantCtx, ses, mp, sqlForCheckRoleExists)
  1304  		if err != nil {
  1305  			return nil, err
  1306  		}
  1307  
  1308  		if !execResultArrayHasData(rsset) {
  1309  			return nil, moerr.NewInternalError(tenantCtx, "there is no role %s", tenant.GetDefaultRole())
  1310  		}
  1311  
  1312  		logDebugf(sessionInfo, "check granted role of user %s.", tenant)
  1313  		//step4.2 : check the role has been granted to the user or not
  1314  		sqlForRoleOfUser, err := getSqlForRoleOfUser(tenantCtx, userID, tenant.GetDefaultRole())
  1315  		if err != nil {
  1316  			return nil, err
  1317  		}
  1318  		rsset, err = executeSQLInBackgroundSession(tenantCtx, ses, mp, sqlForRoleOfUser)
  1319  		if err != nil {
  1320  			return nil, err
  1321  		}
  1322  		if !execResultArrayHasData(rsset) {
  1323  			return nil, moerr.NewInternalError(tenantCtx, "the role %s has not been granted to the user %s",
  1324  				tenant.GetDefaultRole(), tenant.GetUser())
  1325  		}
  1326  
  1327  		defaultRoleID, err = rsset[0].GetInt64(tenantCtx, 0, 0)
  1328  		if err != nil {
  1329  			return nil, err
  1330  		}
  1331  		tenant.SetDefaultRoleID(uint32(defaultRoleID))
  1332  		ses.timestampMap[TSCheckRoleEnd] = time.Now()
  1333  		v2.CheckRoleDurationHistogram.Observe(ses.timestampMap[TSCheckRoleEnd].Sub(ses.timestampMap[TSCheckRoleStart]).Seconds())
  1334  	} else {
  1335  		ses.timestampMap[TSCheckRoleStart] = time.Now()
  1336  		logDebugf(sessionInfo, "check designated role of user %s.", tenant)
  1337  		//the get name of default_role from mo_role
  1338  		sql := getSqlForRoleNameOfRoleId(defaultRoleID)
  1339  		rsset, err = executeSQLInBackgroundSession(tenantCtx, ses, mp, sql)
  1340  		if err != nil {
  1341  			return nil, err
  1342  		}
  1343  		if !execResultArrayHasData(rsset) {
  1344  			return nil, moerr.NewInternalError(tenantCtx, "get the default role of the user %s failed", tenant.GetUser())
  1345  		}
  1346  
  1347  		defaultRole, err = rsset[0].GetString(tenantCtx, 0, 0)
  1348  		if err != nil {
  1349  			return nil, err
  1350  		}
  1351  		tenant.SetDefaultRole(defaultRole)
  1352  		ses.timestampMap[TSCheckRoleEnd] = time.Now()
  1353  		v2.CheckRoleDurationHistogram.Observe(ses.timestampMap[TSCheckRoleEnd].Sub(ses.timestampMap[TSCheckRoleStart]).Seconds())
  1354  	}
  1355  	//------------------------------------------------------------------------------------------------------------------
  1356  	psw, err := GetPassWord(pwd)
  1357  	if err != nil {
  1358  		return nil, err
  1359  	}
  1360  
  1361  	// TO Check password
  1362  	if checkPassword(psw, salt, authResponse) {
  1363  		logDebugf(sessionInfo, "check password succeeded")
  1364  		ses.InitGlobalSystemVariables(tenantCtx)
  1365  	} else {
  1366  		return nil, moerr.NewInternalError(tenantCtx, "check password failed")
  1367  	}
  1368  
  1369  	// If the login information contains the database name, verify if the database exists
  1370  	if dbName != "" {
  1371  		ses.timestampMap[TSCheckDbNameStart] = time.Now()
  1372  		_, err = executeSQLInBackgroundSession(tenantCtx, ses, mp, "use "+dbName)
  1373  		if err != nil {
  1374  			return nil, err
  1375  		}
  1376  		logDebugf(sessionInfo, "check database name succeeded")
  1377  		ses.timestampMap[TSCheckDbNameEnd] = time.Now()
  1378  		v2.CheckDbNameDurationHistogram.Observe(ses.timestampMap[TSCheckDbNameEnd].Sub(ses.timestampMap[TSCheckDbNameStart]).Seconds())
  1379  	}
  1380  	//------------------------------------------------------------------------------------------------------------------
  1381  	// record the id :routine pair in RoutineManager
  1382  	ses.getRoutineManager().accountRoutine.recordRountine(tenantID, ses.getRoutine(), accountVersion)
  1383  	logInfo(ses, sessionInfo, tenant.String())
  1384  
  1385  	return GetPassWord(pwd)
  1386  }
  1387  
  1388  func (ses *Session) MaybeUpgradeTenant(ctx context.Context, curVersion string, tenantID int64) error {
  1389  	// Get mo final version, which is based on the current code version
  1390  	finalVersion := ses.rm.baseService.GetFinalVersion()
  1391  	if versions.Compare(curVersion, finalVersion) <= 0 {
  1392  		return ses.rm.baseService.CheckTenantUpgrade(ctx, tenantID)
  1393  	}
  1394  	return nil
  1395  }
  1396  
  1397  func (ses *Session) UpgradeTenant(ctx context.Context, tenantName string, retryCount uint32, isALLAccount bool) error {
  1398  	// Get mo final version, which is based on the current code version
  1399  	return ses.rm.baseService.UpgradeTenant(ctx, tenantName, retryCount, isALLAccount)
  1400  }
  1401  
  1402  func (ses *Session) InitGlobalSystemVariables(ctx context.Context) error {
  1403  	var err error
  1404  	var rsset []ExecResult
  1405  	ses.timestampMap[TSInitGlobalSysVarStart] = time.Now()
  1406  	defer func() {
  1407  		ses.timestampMap[TSInitGlobalSysVarEnd] = time.Now()
  1408  		v2.InitGlobalSysVarDurationHistogram.Observe(ses.timestampMap[TSInitGlobalSysVarEnd].Sub(ses.timestampMap[TSInitGlobalSysVarStart]).Seconds())
  1409  	}()
  1410  
  1411  	tenantInfo := ses.GetTenantInfo()
  1412  	// if is system account
  1413  	if tenantInfo.IsSysTenant() {
  1414  		sysTenantCtx := defines.AttachAccount(ctx, uint32(sysAccountID), uint32(rootID), uint32(moAdminRoleID))
  1415  
  1416  		// get system variable from mo_mysql_compatibility mode
  1417  		sqlForGetVariables := getSystemVariablesWithAccount(sysAccountID)
  1418  		mp := ses.GetMemPool()
  1419  
  1420  		rsset, err = executeSQLInBackgroundSession(
  1421  			sysTenantCtx,
  1422  			ses,
  1423  			mp,
  1424  			sqlForGetVariables)
  1425  		if err != nil {
  1426  			return err
  1427  		}
  1428  		if execResultArrayHasData(rsset) {
  1429  			for i := uint64(0); i < rsset[0].GetRowCount(); i++ {
  1430  				variable_name, err := rsset[0].GetString(sysTenantCtx, i, 0)
  1431  				if err != nil {
  1432  					return err
  1433  				}
  1434  				variable_value, err := rsset[0].GetString(sysTenantCtx, i, 1)
  1435  				if err != nil {
  1436  					return err
  1437  				}
  1438  
  1439  				if sv, ok := gSysVarsDefs[variable_name]; ok {
  1440  					if !sv.GetDynamic() || (sv.Scope != ScopeGlobal && sv.Scope != ScopeBoth) {
  1441  						continue
  1442  					}
  1443  					val, err := sv.GetType().ConvertFromString(variable_value)
  1444  					if err != nil {
  1445  						errutil.ReportError(ctx, moerr.NewInternalError(context.Background(), "init variable fail: variable %s convert from string value to the system variable type %s failed, bad value %s", variable_name, sv.Type.String(), variable_value))
  1446  						return err
  1447  					}
  1448  					err = ses.InitSetSessionVar(sysTenantCtx, variable_name, val)
  1449  					if err != nil {
  1450  						errutil.ReportError(ctx, moerr.NewInternalError(context.Background(), "init variable fail: variable %s convert from string value to the system variable type %s failed, bad value %s", variable_name, sv.Type.String(), variable_value))
  1451  					}
  1452  				}
  1453  			}
  1454  		} else {
  1455  			return moerr.NewInternalError(sysTenantCtx, "there is no data in mo_mysql_compatibility_mode table for account %s", sysAccountName)
  1456  		}
  1457  	} else {
  1458  		tenantCtx := defines.AttachAccount(ctx, tenantInfo.GetTenantID(), tenantInfo.GetUserID(), uint32(accountAdminRoleID))
  1459  
  1460  		// get system variable from mo_mysql_compatibility mode
  1461  		sqlForGetVariables := getSystemVariablesWithAccount(uint64(tenantInfo.GetTenantID()))
  1462  		mp := ses.GetMemPool()
  1463  
  1464  		rsset, err = executeSQLInBackgroundSession(
  1465  			tenantCtx,
  1466  			ses,
  1467  			mp,
  1468  			sqlForGetVariables)
  1469  		if err != nil {
  1470  			return err
  1471  		}
  1472  		if execResultArrayHasData(rsset) {
  1473  			for i := uint64(0); i < rsset[0].GetRowCount(); i++ {
  1474  				variable_name, err := rsset[0].GetString(tenantCtx, i, 0)
  1475  				if err != nil {
  1476  					return err
  1477  				}
  1478  				variable_value, err := rsset[0].GetString(tenantCtx, i, 1)
  1479  				if err != nil {
  1480  					return err
  1481  				}
  1482  
  1483  				if sv, ok := gSysVarsDefs[variable_name]; ok {
  1484  					if !sv.Dynamic || sv.GetScope() == ScopeSession {
  1485  						continue
  1486  					}
  1487  					val, err := sv.GetType().ConvertFromString(variable_value)
  1488  					if err != nil {
  1489  						return err
  1490  					}
  1491  					err = ses.InitSetSessionVar(tenantCtx, variable_name, val)
  1492  					if err != nil {
  1493  						return err
  1494  					}
  1495  				}
  1496  			}
  1497  		} else {
  1498  			return moerr.NewInternalError(tenantCtx, "there is no data in  mo_mysql_compatibility_mode table for account %s", tenantInfo.GetTenant())
  1499  		}
  1500  	}
  1501  	return err
  1502  }
  1503  
  1504  func (ses *Session) GetPrivilege() *privilege {
  1505  	ses.mu.Lock()
  1506  	defer ses.mu.Unlock()
  1507  	return ses.priv
  1508  }
  1509  
  1510  func (ses *Session) SetPrivilege(priv *privilege) {
  1511  	ses.mu.Lock()
  1512  	defer ses.mu.Unlock()
  1513  	ses.priv = priv
  1514  }
  1515  
  1516  func (ses *Session) SetFromRealUser(b bool) {
  1517  	ses.mu.Lock()
  1518  	defer ses.mu.Unlock()
  1519  	ses.fromRealUser = b
  1520  }
  1521  
  1522  func (ses *Session) GetFromRealUser() bool {
  1523  	ses.mu.Lock()
  1524  	defer ses.mu.Unlock()
  1525  	return ses.fromRealUser
  1526  }
  1527  
  1528  func changeVersion(ctx context.Context, ses *Session, db string) error {
  1529  	var err error
  1530  	if _, ok := bannedCatalogDatabases[db]; ok {
  1531  		return err
  1532  	}
  1533  	version, _ := GetVersionCompatibility(ctx, ses, db)
  1534  	if ses.GetTenantInfo() != nil {
  1535  		ses.GetTenantInfo().SetVersion(version)
  1536  	}
  1537  	return err
  1538  }
  1539  
  1540  // getCNLabels returns requested CN labels.
  1541  func (ses *Session) getCNLabels() map[string]string {
  1542  	return ses.requestLabel
  1543  }
  1544  
  1545  // getSystemVariableValue get the system vaiables value from the mo_mysql_compatibility_mode table
  1546  func (ses *Session) GetGlobalSystemVariableValue(ctx context.Context, varName string) (val interface{}, err error) {
  1547  	var sql string
  1548  	//var err error
  1549  	var erArray []ExecResult
  1550  	var accountId uint32
  1551  	var variableValue string
  1552  	// check the variable name isValid or not
  1553  	_, err = ses.GetGlobalVar(ctx, varName)
  1554  	if err != nil {
  1555  		return nil, err
  1556  	}
  1557  
  1558  	bh := ses.GetBackgroundExec(ctx)
  1559  	defer bh.Close()
  1560  
  1561  	err = bh.Exec(ctx, "begin;")
  1562  	defer func() {
  1563  		err = finishTxn(ctx, bh, err)
  1564  	}()
  1565  	if err != nil {
  1566  		return nil, err
  1567  	}
  1568  	if tenantInfo := ses.GetTenantInfo(); tenantInfo != nil {
  1569  		accountId = tenantInfo.GetTenantID()
  1570  	}
  1571  	sql = getSqlForGetSystemVariableValueWithAccount(uint64(accountId), varName)
  1572  
  1573  	bh.ClearExecResultSet()
  1574  	err = bh.Exec(ctx, sql)
  1575  	if err != nil {
  1576  		return nil, err
  1577  	}
  1578  
  1579  	erArray, err = getResultSet(ctx, bh)
  1580  	if err != nil {
  1581  		return nil, err
  1582  	}
  1583  
  1584  	if execResultArrayHasData(erArray) {
  1585  		variableValue, err = erArray[0].GetString(ctx, 0, 0)
  1586  		if err != nil {
  1587  			return nil, err
  1588  		}
  1589  		if sv, ok := gSysVarsDefs[varName]; ok {
  1590  			val, err = sv.GetType().ConvertFromString(variableValue)
  1591  			if err != nil {
  1592  				return nil, err
  1593  			}
  1594  			return val, nil
  1595  		}
  1596  	}
  1597  
  1598  	return nil, moerr.NewInternalError(ctx, "can not resolve global system variable %s", varName)
  1599  }
  1600  
  1601  func (ses *Session) SetNewResponse(category int, affectedRows uint64, cmd int, d interface{}, isLastStmt bool) *Response {
  1602  	// If the stmt has next stmt, should add SERVER_MORE_RESULTS_EXISTS to the server status.
  1603  	var resp *Response
  1604  	if !isLastStmt {
  1605  		resp = NewResponse(category, affectedRows, 0, 0,
  1606  			ses.GetTxnHandler().GetServerStatus()|SERVER_MORE_RESULTS_EXISTS, cmd, d)
  1607  	} else {
  1608  		resp = NewResponse(category, affectedRows, 0, 0, ses.GetTxnHandler().GetServerStatus(), cmd, d)
  1609  	}
  1610  	return resp
  1611  }
  1612  
  1613  // StatusSession implements the queryservice.Session interface.
  1614  func (ses *Session) StatusSession() *status.Session {
  1615  	var (
  1616  		accountName string
  1617  		userName    string
  1618  		roleName    string
  1619  	)
  1620  
  1621  	accountName, userName, roleName = getUserProfile(ses.GetTenantInfo())
  1622  	//if the query is processing, the end time is invalid.
  1623  	//we can not clear the session info under this condition.
  1624  	if !ses.GetQueryInProgress() {
  1625  		endAt := ses.GetQueryEnd()
  1626  		//if the current time is more than 3 second after the query end time, the session is timeout.
  1627  		//we clear the session statement info
  1628  		//for issue 11976
  1629  		if time.Since(endAt) > 3*time.Second {
  1630  			return &status.Session{
  1631  				NodeID:        ses.getRoutineManager().baseService.ID(),
  1632  				ConnID:        ses.GetConnectionID(),
  1633  				SessionID:     ses.GetUUIDString(),
  1634  				Account:       accountName,
  1635  				User:          userName,
  1636  				Host:          ses.getRoutineManager().baseService.SQLAddress(),
  1637  				DB:            ses.GetDatabaseName(),
  1638  				SessionStart:  ses.GetSessionStart(),
  1639  				Command:       "",
  1640  				Info:          "",
  1641  				TxnID:         uuid2Str(ses.GetTxnId()),
  1642  				StatementID:   "",
  1643  				StatementType: "",
  1644  				QueryType:     "",
  1645  				SQLSourceType: "",
  1646  				QueryStart:    time.Time{},
  1647  				ClientHost:    ses.clientAddr,
  1648  				Role:          roleName,
  1649  				FromProxy:     ses.fromProxy,
  1650  				ProxyHost:     ses.proxyAddr,
  1651  			}
  1652  		}
  1653  	}
  1654  	return &status.Session{
  1655  		NodeID:        ses.getRoutineManager().baseService.ID(),
  1656  		ConnID:        ses.GetConnectionID(),
  1657  		SessionID:     ses.GetUUIDString(),
  1658  		Account:       accountName,
  1659  		User:          userName,
  1660  		Host:          ses.getRoutineManager().baseService.SQLAddress(),
  1661  		DB:            ses.GetDatabaseName(),
  1662  		SessionStart:  ses.GetSessionStart(),
  1663  		Command:       ses.GetCmd().String(),
  1664  		Info:          ses.GetSqlOfStmt(),
  1665  		TxnID:         uuid2Str(ses.GetTxnId()),
  1666  		StatementID:   ses.GetStmtId().String(),
  1667  		StatementType: ses.GetStmtType(),
  1668  		QueryType:     ses.GetQueryType(),
  1669  		SQLSourceType: ses.GetSqlSourceType(),
  1670  		QueryStart:    ses.GetQueryStart(),
  1671  		ClientHost:    ses.clientAddr,
  1672  		Role:          roleName,
  1673  		FromProxy:     ses.fromProxy,
  1674  		ProxyHost:     ses.proxyAddr,
  1675  	}
  1676  }
  1677  
  1678  // getStatusAfterTxnIsEnded
  1679  // !!! only used after the txn is ended.
  1680  // it may be called in the active txn. so, we
  1681  func (ses *Session) getStatusAfterTxnIsEnded(ctx context.Context) uint16 {
  1682  	return extendStatus(ses.GetTxnHandler().GetServerStatus())
  1683  }
  1684  
  1685  func uuid2Str(uid uuid.UUID) string {
  1686  	if bytes.Equal(uid[:], dumpUUID[:]) {
  1687  		return ""
  1688  	}
  1689  	return strings.ReplaceAll(uid.String(), "-", "")
  1690  }
  1691  
  1692  func (ses *Session) SetSessionRoutineStatus(status string) error {
  1693  	var err error
  1694  	if status == tree.AccountStatusRestricted.String() {
  1695  		ses.getRoutine().setResricted(true)
  1696  	} else if status == tree.AccountStatusSuspend.String() {
  1697  		ses.getRoutine().setResricted(false)
  1698  	} else if status == tree.AccountStatusOpen.String() {
  1699  		ses.getRoutine().setResricted(false)
  1700  	} else {
  1701  		err = moerr.NewInternalErrorNoCtx("SetSessionRoutineStatus have invalid status : %s", status)
  1702  	}
  1703  	return err
  1704  }
  1705  
  1706  func checkPlanIsInsertValues(proc *process.Process,
  1707  	p *plan.Plan) (bool, [][]colexec.ExpressionExecutor) {
  1708  	qry := p.GetQuery()
  1709  	if qry != nil {
  1710  		for _, node := range qry.Nodes {
  1711  			if node.NodeType == plan.Node_VALUE_SCAN && node.RowsetData != nil {
  1712  				exprList := make([][]colexec.ExpressionExecutor, len(node.RowsetData.Cols))
  1713  				for i, col := range node.RowsetData.Cols {
  1714  					exprList[i] = make([]colexec.ExpressionExecutor, 0, len(col.Data))
  1715  					for _, data := range col.Data {
  1716  						if data.Pos >= 0 {
  1717  							continue
  1718  						}
  1719  						expr, err := colexec.NewExpressionExecutor(proc, data.Expr)
  1720  						if err != nil {
  1721  							return false, nil
  1722  						}
  1723  						exprList[i] = append(exprList[i], expr)
  1724  					}
  1725  				}
  1726  				return true, exprList
  1727  			}
  1728  		}
  1729  	}
  1730  	return false, nil
  1731  }
  1732  
  1733  func commitAfterMigrate(ses *Session, err error) error {
  1734  	//if ses == nil {
  1735  	//	logutil.Error("session is nil")
  1736  	//	return moerr.NewInternalErrorNoCtx("session is nil")
  1737  	//}
  1738  	//txnHandler := ses.GetTxnHandler()
  1739  	//if txnHandler == nil {
  1740  	//	logutil.Error("txn handler is nil")
  1741  	//	return moerr.NewInternalErrorNoCtx("txn handler is nil")
  1742  	//}
  1743  	//if txnHandler.GetSession() == nil {
  1744  	//	logutil.Error("ses in txn handler is nil")
  1745  	//	return moerr.NewInternalErrorNoCtx("ses in txn handler is nil")
  1746  	//}
  1747  	//defer func() {
  1748  	//	txnHandler.ClearServerStatus(SERVER_STATUS_IN_TRANS)
  1749  	//	txnHandler.ClearOptionBits(OPTION_BEGIN)
  1750  	//}()
  1751  	//if err != nil {
  1752  	//	if rErr := txnHandler.RollbackTxn(); rErr != nil {
  1753  	//		logutil.Errorf("failed to rollback txn: %v", rErr)
  1754  	//	}
  1755  	//	return err
  1756  	//} else {
  1757  	//	if cErr := txnHandler.CommitTxn(); cErr != nil {
  1758  	//		logutil.Errorf("failed to commit txn: %v", cErr)
  1759  	//		return cErr
  1760  	//	}
  1761  	//}
  1762  	return nil
  1763  }
  1764  
  1765  type dbMigration struct {
  1766  	db       string
  1767  	commitFn func(*Session, error) error
  1768  }
  1769  
  1770  func newDBMigration(db string) *dbMigration {
  1771  	return &dbMigration{
  1772  		db:       db,
  1773  		commitFn: commitAfterMigrate,
  1774  	}
  1775  }
  1776  
  1777  func (d *dbMigration) Migrate(ctx context.Context, ses *Session) error {
  1778  	if d.db == "" {
  1779  		return nil
  1780  	}
  1781  	tempExecCtx := &ExecCtx{
  1782  		reqCtx:         ctx,
  1783  		skipRespClient: true,
  1784  		ses:            ses,
  1785  	}
  1786  	return doComQuery(ses, tempExecCtx, &UserInput{sql: "use " + d.db})
  1787  }
  1788  
  1789  type prepareStmtMigration struct {
  1790  	name       string
  1791  	sql        string
  1792  	paramTypes []byte
  1793  	commitFn   func(*Session, error) error
  1794  }
  1795  
  1796  func newPrepareStmtMigration(name string, sql string, paramTypes []byte) *prepareStmtMigration {
  1797  	return &prepareStmtMigration{
  1798  		name:       name,
  1799  		sql:        sql,
  1800  		paramTypes: paramTypes,
  1801  		commitFn:   commitAfterMigrate,
  1802  	}
  1803  }
  1804  
  1805  func (p *prepareStmtMigration) Migrate(ctx context.Context, ses *Session) error {
  1806  	if !strings.HasPrefix(strings.ToLower(p.sql), "prepare") {
  1807  		p.sql = fmt.Sprintf("prepare %s from %s", p.name, p.sql)
  1808  	}
  1809  
  1810  	tempExecCtx := &ExecCtx{
  1811  		reqCtx:            ctx,
  1812  		skipRespClient:    true,
  1813  		ses:               ses,
  1814  		executeParamTypes: p.paramTypes,
  1815  	}
  1816  	return doComQuery(ses, tempExecCtx, &UserInput{sql: p.sql})
  1817  }
  1818  
  1819  func Migrate(ses *Session, req *query.MigrateConnToRequest) error {
  1820  	parameters := getGlobalPu().SV
  1821  
  1822  	//all offspring related to the request inherit the txnCtx
  1823  	cancelRequestCtx, cancelRequestFunc := context.WithTimeout(ses.GetTxnHandler().GetTxnCtx(), parameters.SessionTimeout.Duration)
  1824  	defer cancelRequestFunc()
  1825  	ses.UpdateDebugString()
  1826  	tenant := ses.GetTenantInfo()
  1827  	nodeCtx := cancelRequestCtx
  1828  	if ses.getRoutineManager() != nil && ses.getRoutineManager().baseService != nil {
  1829  		nodeCtx = context.WithValue(cancelRequestCtx, defines.NodeIDKey{}, ses.getRoutineManager().baseService.ID())
  1830  	}
  1831  	ctx := defines.AttachAccount(nodeCtx, tenant.GetTenantID(), tenant.GetUserID(), tenant.GetDefaultRoleID())
  1832  
  1833  	accountID, err := defines.GetAccountId(ctx)
  1834  
  1835  	if err != nil {
  1836  		logutil.Errorf("failed to get account ID: %v", err)
  1837  		return err
  1838  	}
  1839  	userID := defines.GetUserId(ctx)
  1840  	logutil.Infof("do migration on connection %d, db: %s, account id: %d, user id: %d",
  1841  		req.ConnID, req.DB, accountID, userID)
  1842  
  1843  	dbm := newDBMigration(req.DB)
  1844  	if err := dbm.Migrate(ctx, ses); err != nil {
  1845  		return err
  1846  	}
  1847  
  1848  	var maxStmtID uint32
  1849  	for _, p := range req.PrepareStmts {
  1850  		if p == nil {
  1851  			continue
  1852  		}
  1853  		pm := newPrepareStmtMigration(p.Name, p.SQL, p.ParamTypes)
  1854  		if err := pm.Migrate(ctx, ses); err != nil {
  1855  			return err
  1856  		}
  1857  		id := parsePrepareStmtID(p.Name)
  1858  		if id > maxStmtID {
  1859  			maxStmtID = id
  1860  		}
  1861  	}
  1862  	if maxStmtID > 0 {
  1863  		ses.SetLastStmtID(maxStmtID)
  1864  	}
  1865  	return nil
  1866  }