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

     1  // Copyright 2022 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  	"context"
    19  	"io"
    20  	"time"
    21  
    22  	"github.com/fagongzi/goetty/v2/buf"
    23  	"github.com/google/uuid"
    24  
    25  	"github.com/matrixorigin/matrixone/pkg/common/buffer"
    26  	"github.com/matrixorigin/matrixone/pkg/common/mpool"
    27  	"github.com/matrixorigin/matrixone/pkg/config"
    28  	"github.com/matrixorigin/matrixone/pkg/pb/timestamp"
    29  	"github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace"
    30  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    31  
    32  	"github.com/matrixorigin/matrixone/pkg/container/batch"
    33  	"github.com/matrixorigin/matrixone/pkg/container/types"
    34  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    35  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    36  	"github.com/matrixorigin/matrixone/pkg/sql/colexec"
    37  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
    38  	plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan"
    39  	"github.com/matrixorigin/matrixone/pkg/txn/client"
    40  	"github.com/matrixorigin/matrixone/pkg/util"
    41  )
    42  
    43  const (
    44  	DefaultRpcBufferSize = 1 << 10
    45  )
    46  
    47  type (
    48  	TxnOperator = client.TxnOperator
    49  	TxnClient   = client.TxnClient
    50  	TxnOption   = client.TxnOption
    51  )
    52  
    53  type ComputationRunner interface {
    54  	Run(ts uint64) (*util.RunResult, error)
    55  }
    56  
    57  // ComputationWrapper is the wrapper of the computation
    58  type ComputationWrapper interface {
    59  	ComputationRunner
    60  	GetAst() tree.Statement
    61  
    62  	GetProcess() *process.Process
    63  
    64  	GetColumns(ctx context.Context) ([]interface{}, error)
    65  
    66  	Compile(any any, fill func(*batch.Batch) error) (interface{}, error)
    67  
    68  	GetUUID() []byte
    69  
    70  	RecordExecPlan(ctx context.Context) error
    71  
    72  	GetLoadTag() bool
    73  
    74  	GetServerStatus() uint16
    75  	Clear()
    76  	Plan() *plan.Plan
    77  	ResetPlanAndStmt(stmt tree.Statement)
    78  	Free()
    79  }
    80  
    81  type ColumnInfo interface {
    82  	GetName() string
    83  
    84  	GetType() types.T
    85  }
    86  
    87  var _ ColumnInfo = &engineColumnInfo{}
    88  
    89  type TableInfo interface {
    90  	GetColumns()
    91  }
    92  
    93  type engineColumnInfo struct {
    94  	name string
    95  	typ  types.Type
    96  }
    97  
    98  func (ec *engineColumnInfo) GetName() string {
    99  	return ec.name
   100  }
   101  
   102  func (ec *engineColumnInfo) GetType() types.T {
   103  	return ec.typ.Oid
   104  }
   105  
   106  type PrepareStmt struct {
   107  	Name           string
   108  	Sql            string
   109  	PreparePlan    *plan.Plan
   110  	PrepareStmt    tree.Statement
   111  	ParamTypes     []byte
   112  	IsInsertValues bool
   113  	InsertBat      *batch.Batch
   114  	proc           *process.Process
   115  
   116  	exprList [][]colexec.ExpressionExecutor
   117  
   118  	params              *vector.Vector
   119  	getFromSendLongData map[int]struct{}
   120  }
   121  
   122  /*
   123  Disguise the COMMAND CMD_FIELD_LIST as sql query.
   124  */
   125  const (
   126  	cmdFieldListSql    = "__++__internal_cmd_field_list"
   127  	cmdFieldListSqlLen = len(cmdFieldListSql)
   128  	cloudUserTag       = "cloud_user"
   129  	cloudNoUserTag     = "cloud_nonuser"
   130  	saveResultTag      = "save_result"
   131  )
   132  
   133  var _ tree.Statement = &InternalCmdFieldList{}
   134  
   135  // InternalCmdFieldList the CMD_FIELD_LIST statement
   136  type InternalCmdFieldList struct {
   137  	tableName string
   138  }
   139  
   140  // Free implements tree.Statement.
   141  func (icfl *InternalCmdFieldList) Free() {
   142  }
   143  
   144  func (icfl *InternalCmdFieldList) String() string {
   145  	return makeCmdFieldListSql(icfl.tableName)
   146  }
   147  
   148  func (icfl *InternalCmdFieldList) Format(ctx *tree.FmtCtx) {
   149  	ctx.WriteString(makeCmdFieldListSql(icfl.tableName))
   150  }
   151  
   152  func (icfl *InternalCmdFieldList) StmtKind() tree.StmtKind {
   153  	return tree.MakeStmtKind(tree.OUTPUT_STATUS, tree.RESP_BY_SITUATION, tree.EXEC_IN_FRONTEND)
   154  }
   155  
   156  func (icfl *InternalCmdFieldList) GetStatementType() string { return "InternalCmd" }
   157  func (icfl *InternalCmdFieldList) GetQueryType() string     { return tree.QueryTypeDQL }
   158  
   159  // ExecResult is the result interface of the execution
   160  type ExecResult interface {
   161  	GetRowCount() uint64
   162  
   163  	GetString(ctx context.Context, rindex, cindex uint64) (string, error)
   164  
   165  	GetUint64(ctx context.Context, rindex, cindex uint64) (uint64, error)
   166  
   167  	GetInt64(ctx context.Context, rindex, cindex uint64) (int64, error)
   168  }
   169  
   170  func execResultArrayHasData(arr []ExecResult) bool {
   171  	return len(arr) != 0 && arr[0].GetRowCount() != 0
   172  }
   173  
   174  // BackgroundExec executes the sql in background session without network output.
   175  type BackgroundExec interface {
   176  	Close()
   177  	Exec(context.Context, string) error
   178  	ExecRestore(context.Context, string, uint32, uint32) error
   179  	ExecStmt(context.Context, tree.Statement) error
   180  	GetExecResultSet() []interface{}
   181  	ClearExecResultSet()
   182  
   183  	GetExecResultBatches() []*batch.Batch
   184  	ClearExecResultBatches()
   185  	Clear()
   186  }
   187  
   188  var _ BackgroundExec = &backExec{}
   189  
   190  type unknownStatementType struct {
   191  	tree.StatementType
   192  }
   193  
   194  func (unknownStatementType) GetStatementType() string { return "Unknown" }
   195  func (unknownStatementType) GetQueryType() string     { return tree.QueryTypeOth }
   196  
   197  func getStatementType(stmt tree.Statement) tree.StatementType {
   198  	switch stmt.(type) {
   199  	case tree.StatementType:
   200  		return stmt
   201  	default:
   202  		return unknownStatementType{}
   203  	}
   204  }
   205  
   206  // TableInfoCache tableInfos of a database
   207  //type TableInfoCache struct {
   208  //	db         string
   209  //	tableInfos map[string][]ColumnInfo
   210  //}
   211  
   212  // outputPool outputs the data
   213  type outputPool interface {
   214  	resetLineStr()
   215  
   216  	reset()
   217  
   218  	getEmptyRow() ([]interface{}, error)
   219  
   220  	flush() error
   221  }
   222  
   223  func (prepareStmt *PrepareStmt) Close() {
   224  	if prepareStmt.params != nil {
   225  		prepareStmt.params.Free(prepareStmt.proc.Mp())
   226  	}
   227  	if prepareStmt.InsertBat != nil {
   228  		prepareStmt.InsertBat.SetCnt(1)
   229  		prepareStmt.InsertBat.Clean(prepareStmt.proc.Mp())
   230  		prepareStmt.InsertBat = nil
   231  	}
   232  	if prepareStmt.exprList != nil {
   233  		for _, exprs := range prepareStmt.exprList {
   234  			for _, expr := range exprs {
   235  				expr.Free()
   236  			}
   237  		}
   238  	}
   239  	if prepareStmt.PrepareStmt != nil {
   240  		prepareStmt.PrepareStmt.Free()
   241  	}
   242  }
   243  
   244  var _ buf.Allocator = &SessionAllocator{}
   245  
   246  type SessionAllocator struct {
   247  	mp *mpool.MPool
   248  }
   249  
   250  func NewSessionAllocator(pu *config.ParameterUnit) *SessionAllocator {
   251  	pool, err := mpool.NewMPool("frontend-goetty-pool-cn-level", pu.SV.GuestMmuLimitation, mpool.NoFixed)
   252  	if err != nil {
   253  		panic(err)
   254  	}
   255  	ret := &SessionAllocator{mp: pool}
   256  	return ret
   257  }
   258  
   259  func (s *SessionAllocator) Alloc(capacity int) []byte {
   260  	alloc, err := s.mp.Alloc(capacity)
   261  	if err != nil {
   262  		panic(err)
   263  	}
   264  	return alloc
   265  }
   266  
   267  func (s SessionAllocator) Free(bs []byte) {
   268  	s.mp.Free(bs)
   269  }
   270  
   271  var _ FeSession = &Session{}
   272  var _ FeSession = &backSession{}
   273  
   274  type FeSession interface {
   275  	GetTimeZone() *time.Location
   276  	GetStatsCache() *plan2.StatsCache
   277  	GetUserName() string
   278  	GetSql() string
   279  	GetAccountId() uint32
   280  	GetTenantInfo() *TenantInfo
   281  	GetBackgroundExec(ctx context.Context) BackgroundExec
   282  	GetRawBatchBackgroundExec(ctx context.Context) BackgroundExec
   283  	GetGlobalSystemVariableValue(ctx context.Context, name string) (interface{}, error)
   284  	GetSessionVar(ctx context.Context, name string) (interface{}, error)
   285  	GetUserDefinedVar(name string) (SystemVariableType, *UserDefinedVar, error)
   286  	GetDebugString() string
   287  	GetFromRealUser() bool
   288  	getLastCommitTS() timestamp.Timestamp
   289  	GetTenantName() string
   290  	SetTxnId(i []byte)
   291  	GetTxnId() uuid.UUID
   292  	GetStmtId() uuid.UUID
   293  	GetSqlOfStmt() string
   294  	updateLastCommitTS(ts timestamp.Timestamp)
   295  	GetMysqlProtocol() MysqlProtocol
   296  	GetTxnHandler() *TxnHandler
   297  	GetDatabaseName() string
   298  	SetDatabaseName(db string)
   299  	GetMysqlResultSet() *MysqlResultSet
   300  	GetGlobalVar(ctx context.Context, name string) (interface{}, error)
   301  	SetNewResponse(category int, affectedRows uint64, cmd int, d interface{}, isLastStmt bool) *Response
   302  	GetTxnCompileCtx() *TxnCompilerContext
   303  	GetCmd() CommandType
   304  	IsBackgroundSession() bool
   305  	GetPrepareStmt(ctx context.Context, name string) (*PrepareStmt, error)
   306  	CountPayload(i int)
   307  	RemovePrepareStmt(name string)
   308  	SetShowStmtType(statement ShowStatementType)
   309  	SetSql(sql string)
   310  	GetMemPool() *mpool.MPool
   311  	GetProc() *process.Process
   312  	GetLastInsertID() uint64
   313  	GetSqlHelper() *SqlHelper
   314  	GetBuffer() *buffer.Buffer
   315  	GetStmtProfile() *process.StmtProfile
   316  	CopySeqToProc(proc *process.Process)
   317  	getQueryId(internal bool) []string
   318  	SetMysqlResultSet(mrs *MysqlResultSet)
   319  	GetConnectionID() uint32
   320  	IsDerivedStmt() bool
   321  	SetAccountId(uint32)
   322  	SetPlan(plan *plan.Plan)
   323  	SetData([][]interface{})
   324  	GetIsInternal() bool
   325  	getCNLabels() map[string]string
   326  	GetUpstream() FeSession
   327  	cleanCache()
   328  	getNextProcessId() string
   329  	GetSqlCount() uint64
   330  	addSqlCount(a uint64)
   331  	GetStmtInfo() *motrace.StatementInfo
   332  	GetTxnInfo() string
   333  	GetUUID() []byte
   334  	SendRows() int64
   335  	SetTStmt(stmt *motrace.StatementInfo)
   336  	GetUUIDString() string
   337  	DisableTrace() bool
   338  	Close()
   339  	Clear()
   340  	getCachedPlan(sql string) *cachedPlan
   341  }
   342  
   343  type ExecCtx struct {
   344  	reqCtx      context.Context
   345  	prepareStmt *PrepareStmt
   346  	runResult   *util.RunResult
   347  	//stmt will be replaced by the Execute
   348  	stmt tree.Statement
   349  	//isLastStmt : true denotes the last statement in the query
   350  	isLastStmt bool
   351  	// tenant name
   352  	tenant          string
   353  	userName        string
   354  	sqlOfStmt       string
   355  	cw              ComputationWrapper
   356  	runner          ComputationRunner
   357  	loadLocalWriter *io.PipeWriter
   358  	proc            *process.Process
   359  	proto           MysqlProtocol
   360  	ses             FeSession
   361  	txnOpt          FeTxnOption
   362  	cws             []ComputationWrapper
   363  	input           *UserInput
   364  	//In the session migration, skip the response to the client
   365  	skipRespClient bool
   366  	//In the session migration, executeParamTypes for the EXECUTE stmt should be migrated
   367  	//from the old session to the new session.
   368  	executeParamTypes []byte
   369  }
   370  
   371  // outputCallBackFunc is the callback function to send the result to the client.
   372  // parameters:
   373  //
   374  //	FeSession
   375  //	ExecCtx
   376  //	batch.Batch
   377  type outputCallBackFunc func(FeSession, *ExecCtx, *batch.Batch) error
   378  
   379  // TODO: shared component among the session implmentation
   380  type feSessionImpl struct {
   381  	pool          *mpool.MPool
   382  	proto         MysqlProtocol
   383  	buf           *buffer.Buffer
   384  	stmtProfile   process.StmtProfile
   385  	tenant        *TenantInfo
   386  	txnHandler    *TxnHandler
   387  	txnCompileCtx *TxnCompilerContext
   388  	mrs           *MysqlResultSet
   389  	//it gets the result set from the pipeline and send it to the client
   390  	outputCallback outputCallBackFunc
   391  
   392  	//all the result set of executing the sql in background task
   393  	allResultSet []*MysqlResultSet
   394  	rs           *plan.ResultColDef
   395  
   396  	// result batches of executing the sql in background task
   397  	// set by func batchFetcher
   398  	resultBatches []*batch.Batch
   399  
   400  	//derivedStmt denotes the sql or statement that derived from the user input statement.
   401  	//a new internal statement derived from the statement the user input and executed during
   402  	// the execution of it in the same transaction.
   403  	//
   404  	//For instance
   405  	//	select nextval('seq_15')
   406  	//  nextval internally will derive two sql (a select and an update). the two sql are executed
   407  	//	in the same transaction.
   408  	derivedStmt bool
   409  
   410  	gSysVars *GlobalSystemVariables
   411  	// when starting a transaction in session, the snapshot ts of the transaction
   412  	// is to get a TN push to CN to get the maximum commitTS. but there is a problem,
   413  	// when the last transaction ends and the next one starts, it is possible that the
   414  	// log of the last transaction has not been pushed to CN, we need to wait until at
   415  	// least the commit of the last transaction log of the previous transaction arrives.
   416  	lastCommitTS timestamp.Timestamp
   417  	upstream     *Session
   418  	sql          string
   419  	accountId    uint32
   420  	label        map[string]string
   421  	timeZone     *time.Location
   422  
   423  	sqlCount     uint64
   424  	uuid         uuid.UUID
   425  	debugStr     string
   426  	disableTrace bool
   427  }
   428  
   429  func (ses *feSessionImpl) Close() {
   430  	ses.proto = nil
   431  	ses.mrs = nil
   432  	if ses.txnHandler != nil {
   433  		ses.txnHandler = nil
   434  	}
   435  	if ses.txnCompileCtx != nil {
   436  		ses.txnCompileCtx.execCtx = nil
   437  		ses.txnCompileCtx.snapshot = nil
   438  		ses.txnCompileCtx.views = nil
   439  		ses.txnCompileCtx = nil
   440  	}
   441  	ses.sql = ""
   442  	ses.gSysVars = nil
   443  	ses.allResultSet = nil
   444  	ses.tenant = nil
   445  	ses.debugStr = ""
   446  	ses.rs = nil
   447  	ses.ClearStmtProfile()
   448  	for _, bat := range ses.resultBatches {
   449  		bat.Clean(ses.pool)
   450  	}
   451  	if ses.buf != nil {
   452  		ses.buf.Free()
   453  		ses.buf = nil
   454  	}
   455  	ses.upstream = nil
   456  }
   457  
   458  func (ses *feSessionImpl) Clear() {
   459  	if ses == nil {
   460  		return
   461  	}
   462  	ses.ClearAllMysqlResultSet()
   463  	ses.ClearResultBatches()
   464  }
   465  
   466  func (ses *feSessionImpl) SetDatabaseName(db string) {
   467  	ses.proto.SetDatabaseName(db)
   468  	ses.txnCompileCtx.SetDatabase(db)
   469  }
   470  
   471  func (ses *feSessionImpl) GetDatabaseName() string {
   472  	return ses.proto.GetDatabaseName()
   473  }
   474  
   475  func (ses *feSessionImpl) GetUserName() string {
   476  	return ses.proto.GetUserName()
   477  }
   478  
   479  func (ses *feSessionImpl) DisableTrace() bool {
   480  	return ses.disableTrace
   481  }
   482  
   483  func (ses *feSessionImpl) SetMemPool(mp *mpool.MPool) {
   484  	ses.pool = mp
   485  }
   486  
   487  func (ses *feSessionImpl) GetMemPool() *mpool.MPool {
   488  	return ses.pool
   489  }
   490  
   491  func (ses *feSessionImpl) GetMysqlProtocol() MysqlProtocol {
   492  	return ses.proto
   493  }
   494  
   495  func (ses *feSessionImpl) ReplaceProtocol(proto MysqlProtocol) MysqlProtocol {
   496  	old := ses.proto
   497  	ses.proto = proto
   498  	return old
   499  }
   500  
   501  func (ses *feSessionImpl) GetBuffer() *buffer.Buffer {
   502  	return ses.buf
   503  }
   504  
   505  func (ses *feSessionImpl) GetStmtProfile() *process.StmtProfile {
   506  	return &ses.stmtProfile
   507  }
   508  
   509  func (ses *feSessionImpl) ClearStmtProfile() {
   510  	ses.stmtProfile.Clear()
   511  }
   512  
   513  func (ses *feSessionImpl) SetTxnId(id []byte) {
   514  	ses.stmtProfile.SetTxnId(id)
   515  }
   516  
   517  func (ses *feSessionImpl) GetTxnId() uuid.UUID {
   518  	return ses.stmtProfile.GetTxnId()
   519  }
   520  
   521  func (ses *feSessionImpl) SetStmtId(id uuid.UUID) {
   522  	ses.stmtProfile.SetStmtId(id)
   523  }
   524  
   525  func (ses *feSessionImpl) GetStmtId() uuid.UUID {
   526  	return ses.stmtProfile.GetStmtId()
   527  }
   528  
   529  func (ses *feSessionImpl) SetStmtType(st string) {
   530  	ses.stmtProfile.SetStmtType(st)
   531  }
   532  
   533  func (ses *feSessionImpl) GetStmtType() string {
   534  	return ses.stmtProfile.GetStmtType()
   535  }
   536  
   537  func (ses *feSessionImpl) SetQueryType(qt string) {
   538  	ses.stmtProfile.SetQueryType(qt)
   539  }
   540  
   541  func (ses *feSessionImpl) GetQueryType() string {
   542  	return ses.stmtProfile.GetQueryType()
   543  }
   544  
   545  func (ses *feSessionImpl) SetSqlSourceType(st string) {
   546  	ses.stmtProfile.SetSqlSourceType(st)
   547  }
   548  
   549  func (ses *feSessionImpl) GetSqlSourceType() string {
   550  	return ses.stmtProfile.GetSqlSourceType()
   551  }
   552  
   553  func (ses *feSessionImpl) SetQueryStart(t time.Time) {
   554  	ses.stmtProfile.SetQueryStart(t)
   555  }
   556  
   557  func (ses *feSessionImpl) GetQueryStart() time.Time {
   558  	return ses.stmtProfile.GetQueryStart()
   559  }
   560  
   561  func (ses *feSessionImpl) SetSqlOfStmt(sot string) {
   562  	ses.stmtProfile.SetSqlOfStmt(sot)
   563  }
   564  
   565  func (ses *feSessionImpl) GetSqlOfStmt() string {
   566  	return ses.stmtProfile.GetSqlOfStmt()
   567  }
   568  
   569  func (ses *feSessionImpl) GetTenantInfo() *TenantInfo {
   570  	return ses.tenant
   571  }
   572  
   573  func (ses *feSessionImpl) SetTenantInfo(ti *TenantInfo) {
   574  	ses.tenant = ti
   575  }
   576  
   577  func (ses *feSessionImpl) GetTxnHandler() *TxnHandler {
   578  	return ses.txnHandler
   579  }
   580  
   581  func (ses *feSessionImpl) GetTxnCompileCtx() *TxnCompilerContext {
   582  	return ses.txnCompileCtx
   583  }
   584  
   585  func (ses *feSessionImpl) SetMysqlResultSet(mrs *MysqlResultSet) {
   586  	ses.mrs = mrs
   587  }
   588  
   589  func (ses *feSessionImpl) GetMysqlResultSet() *MysqlResultSet {
   590  	return ses.mrs
   591  }
   592  
   593  func (ses *feSessionImpl) SetOutputCallback(callback outputCallBackFunc) {
   594  	ses.outputCallback = callback
   595  }
   596  
   597  func (ses *feSessionImpl) SetMysqlResultSetOfBackgroundTask(mrs *MysqlResultSet) {
   598  	if len(ses.allResultSet) == 0 {
   599  		ses.allResultSet = append(ses.allResultSet, mrs)
   600  	}
   601  }
   602  
   603  func (ses *feSessionImpl) GetAllMysqlResultSet() []*MysqlResultSet {
   604  	return ses.allResultSet
   605  }
   606  
   607  func (ses *feSessionImpl) ClearAllMysqlResultSet() {
   608  	if ses.allResultSet != nil {
   609  		ses.allResultSet = ses.allResultSet[:0]
   610  	}
   611  }
   612  
   613  func (ses *feSessionImpl) SaveResultSet() {
   614  	if len(ses.allResultSet) == 0 && ses.mrs != nil {
   615  		ses.allResultSet = []*MysqlResultSet{ses.mrs}
   616  	}
   617  }
   618  
   619  func (ses *feSessionImpl) IsDerivedStmt() bool {
   620  	return ses.derivedStmt
   621  }
   622  
   623  // ReplaceDerivedStmt sets the derivedStmt and returns the previous value.
   624  // if b is true, executing a derived statement.
   625  func (ses *feSessionImpl) ReplaceDerivedStmt(b bool) bool {
   626  	prev := ses.derivedStmt
   627  	ses.derivedStmt = b
   628  	return prev
   629  }
   630  
   631  func (ses *feSessionImpl) updateLastCommitTS(lastCommitTS timestamp.Timestamp) {
   632  	if lastCommitTS.Greater(ses.lastCommitTS) {
   633  		ses.lastCommitTS = lastCommitTS
   634  	}
   635  	if ses.upstream != nil {
   636  		ses.upstream.updateLastCommitTS(lastCommitTS)
   637  	}
   638  }
   639  
   640  func (ses *feSessionImpl) getLastCommitTS() timestamp.Timestamp {
   641  	minTS := ses.lastCommitTS
   642  	if ses.upstream != nil {
   643  		v := ses.upstream.getLastCommitTS()
   644  		if v.Greater(minTS) {
   645  			minTS = v
   646  		}
   647  	}
   648  	return minTS
   649  }
   650  
   651  func (ses *feSessionImpl) GetUpstream() FeSession {
   652  	return ses.upstream
   653  }
   654  
   655  // ClearResultBatches does not call Batch.Clear().
   656  func (ses *feSessionImpl) ClearResultBatches() {
   657  	ses.resultBatches = nil
   658  }
   659  
   660  func (ses *feSessionImpl) GetResultBatches() []*batch.Batch {
   661  	return ses.resultBatches
   662  }
   663  
   664  func (ses *feSessionImpl) AppendResultBatch(bat *batch.Batch) error {
   665  	copied, err := bat.Dup(ses.pool)
   666  	if err != nil {
   667  		return err
   668  	}
   669  	ses.resultBatches = append(ses.resultBatches, copied)
   670  	return nil
   671  }
   672  
   673  func (ses *feSessionImpl) GetGlobalSysVars() *GlobalSystemVariables {
   674  	return ses.gSysVars
   675  }
   676  
   677  func (ses *feSessionImpl) SetSql(sql string) {
   678  	ses.sql = sql
   679  }
   680  
   681  func (ses *feSessionImpl) GetSql() string {
   682  	return ses.sql
   683  }
   684  
   685  func (ses *feSessionImpl) GetAccountId() uint32 {
   686  	return ses.accountId
   687  }
   688  
   689  func (ses *feSessionImpl) SetAccountId(u uint32) {
   690  	ses.accountId = u
   691  }
   692  
   693  func (ses *feSessionImpl) SetTimeZone(loc *time.Location) {
   694  	ses.timeZone = loc
   695  }
   696  
   697  func (ses *feSessionImpl) GetTimeZone() *time.Location {
   698  	return ses.timeZone
   699  }
   700  
   701  func (ses *feSessionImpl) GetSqlCount() uint64 {
   702  	return ses.sqlCount
   703  }
   704  
   705  func (ses *feSessionImpl) addSqlCount(a uint64) {
   706  	ses.sqlCount += a
   707  }
   708  
   709  func (ses *feSessionImpl) GetUUID() []byte {
   710  	return ses.uuid[:]
   711  }
   712  
   713  func (ses *feSessionImpl) GetUUIDString() string {
   714  	return ses.uuid.String()
   715  }
   716  
   717  func (ses *Session) GetDebugString() string {
   718  	ses.mu.Lock()
   719  	defer ses.mu.Unlock()
   720  	return ses.debugStr
   721  }