github.com/matrixorigin/matrixone@v0.7.0/pkg/frontend/mysql_cmd_executor.go (about)

     1  // Copyright 2021 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package frontend
    16  
    17  import (
    18  	"bytes"
    19  	"context"
    20  	"encoding/binary"
    21  	"encoding/json"
    22  	"fmt"
    23  	"io"
    24  	"math"
    25  	"os"
    26  	"reflect"
    27  	"sort"
    28  	"strconv"
    29  	"strings"
    30  	"sync"
    31  	"time"
    32  
    33  	"github.com/fagongzi/goetty/v2"
    34  	"github.com/matrixorigin/matrixone/pkg/sql/util"
    35  	"golang.org/x/sync/errgroup"
    36  
    37  	"github.com/matrixorigin/matrixone/pkg/common/mpool"
    38  	"github.com/matrixorigin/matrixone/pkg/common/runtime"
    39  	"github.com/matrixorigin/matrixone/pkg/txn/clock"
    40  
    41  	"github.com/matrixorigin/matrixone/pkg/catalog"
    42  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    43  	"github.com/matrixorigin/matrixone/pkg/sql/colexec"
    44  
    45  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    46  	logservicepb "github.com/matrixorigin/matrixone/pkg/pb/logservice"
    47  	"github.com/matrixorigin/matrixone/pkg/sql/compile"
    48  	plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan"
    49  	"github.com/matrixorigin/matrixone/pkg/sql/plan/explain"
    50  
    51  	"github.com/matrixorigin/matrixone/pkg/container/batch"
    52  	"github.com/matrixorigin/matrixone/pkg/container/nulls"
    53  	"github.com/matrixorigin/matrixone/pkg/container/types"
    54  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    55  	"github.com/matrixorigin/matrixone/pkg/defines"
    56  	"github.com/matrixorigin/matrixone/pkg/logutil"
    57  	"github.com/matrixorigin/matrixone/pkg/sql/parsers"
    58  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect"
    59  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect/mysql"
    60  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
    61  	"github.com/matrixorigin/matrixone/pkg/util/metric"
    62  	"github.com/matrixorigin/matrixone/pkg/vm/engine"
    63  	"github.com/matrixorigin/matrixone/pkg/vm/engine/memoryengine"
    64  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    65  
    66  	"github.com/matrixorigin/matrixone/pkg/util/trace"
    67  	"github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace"
    68  
    69  	"github.com/google/uuid"
    70  )
    71  
    72  func onlyCreateStatementErrorInfo() string {
    73  	return "Only CREATE of DDL is supported in transactions"
    74  }
    75  
    76  func administrativeCommandIsUnsupportedInTxnErrorInfo() string {
    77  	return "administrative command is unsupported in transactions"
    78  }
    79  
    80  func parameterModificationInTxnErrorInfo() string {
    81  	return "Uncommitted transaction exists. Please commit or rollback first."
    82  }
    83  
    84  func unclassifiedStatementInUncommittedTxnErrorInfo() string {
    85  	return "unclassified statement appears in uncommitted transaction"
    86  }
    87  
    88  func abortTransactionErrorInfo() string {
    89  	return "Previous DML conflicts with existing constraints or data format. This transaction has to be aborted"
    90  }
    91  
    92  func writeWriteConflictsErrorInfo() string {
    93  	return "Write conflicts detected. Previous transaction need to be aborted."
    94  }
    95  
    96  const (
    97  	prefixPrepareStmtName       = "__mo_stmt_id"
    98  	prefixPrepareStmtSessionVar = "__mo_stmt_var"
    99  )
   100  
   101  func getPrepareStmtName(stmtID uint32) string {
   102  	return fmt.Sprintf("%s_%d", prefixPrepareStmtName, stmtID)
   103  }
   104  
   105  func GetPrepareStmtID(ctx context.Context, name string) (int, error) {
   106  	idx := len(prefixPrepareStmtName) + 1
   107  	if idx >= len(name) {
   108  		return -1, moerr.NewInternalError(ctx, "can not get Prepare stmtID")
   109  	}
   110  	return strconv.Atoi(name[idx:])
   111  }
   112  
   113  func getPrepareStmtSessionVarName(index int) string {
   114  	return fmt.Sprintf("%s_%d", prefixPrepareStmtSessionVar, index)
   115  }
   116  
   117  // TableInfoCache tableInfos of a database
   118  type TableInfoCache struct {
   119  	db         string
   120  	tableInfos map[string][]ColumnInfo
   121  }
   122  
   123  type MysqlCmdExecutor struct {
   124  	CmdExecutorImpl
   125  
   126  	//for cmd 0x4
   127  	TableInfoCache
   128  
   129  	//the count of sql has been processed
   130  	sqlCount uint64
   131  
   132  	ses *Session
   133  
   134  	routineMgr *RoutineManager
   135  
   136  	cancelRequestFunc context.CancelFunc
   137  
   138  	doQueryFunc doComQueryFunc
   139  
   140  	mu sync.Mutex
   141  }
   142  
   143  func (mce *MysqlCmdExecutor) CancelRequest() {
   144  	mce.mu.Lock()
   145  	defer mce.mu.Unlock()
   146  	if mce.cancelRequestFunc != nil {
   147  		mce.cancelRequestFunc()
   148  	}
   149  }
   150  
   151  func (mce *MysqlCmdExecutor) ChooseDoQueryFunc(choice bool) {
   152  	mce.mu.Lock()
   153  	defer mce.mu.Unlock()
   154  	if choice {
   155  		mce.doQueryFunc = mce.doComQueryInProgress
   156  	} else {
   157  		mce.doQueryFunc = mce.doComQuery
   158  	}
   159  }
   160  
   161  func (mce *MysqlCmdExecutor) GetDoQueryFunc() doComQueryFunc {
   162  	mce.mu.Lock()
   163  	defer mce.mu.Unlock()
   164  	if mce.doQueryFunc == nil {
   165  		mce.doQueryFunc = mce.doComQuery
   166  	}
   167  	return mce.doQueryFunc
   168  }
   169  
   170  func (mce *MysqlCmdExecutor) SetSession(ses *Session) {
   171  	mce.mu.Lock()
   172  	defer mce.mu.Unlock()
   173  	mce.ses = ses
   174  }
   175  
   176  func (mce *MysqlCmdExecutor) GetSession() *Session {
   177  	mce.mu.Lock()
   178  	defer mce.mu.Unlock()
   179  	return mce.ses
   180  }
   181  
   182  // get new process id
   183  func (mce *MysqlCmdExecutor) getNextProcessId() string {
   184  	/*
   185  		temporary method:
   186  		routineId + sqlCount
   187  	*/
   188  	routineId := mce.GetSession().GetMysqlProtocol().ConnectionID()
   189  	return fmt.Sprintf("%d%d", routineId, mce.GetSqlCount())
   190  }
   191  
   192  func (mce *MysqlCmdExecutor) GetSqlCount() uint64 {
   193  	mce.mu.Lock()
   194  	defer mce.mu.Unlock()
   195  	return mce.sqlCount
   196  }
   197  
   198  func (mce *MysqlCmdExecutor) addSqlCount(a uint64) {
   199  	mce.mu.Lock()
   200  	defer mce.mu.Unlock()
   201  	mce.sqlCount += a
   202  }
   203  
   204  func (mce *MysqlCmdExecutor) SetRoutineManager(mgr *RoutineManager) {
   205  	mce.mu.Lock()
   206  	defer mce.mu.Unlock()
   207  	mce.routineMgr = mgr
   208  }
   209  
   210  func (mce *MysqlCmdExecutor) GetRoutineManager() *RoutineManager {
   211  	mce.mu.Lock()
   212  	defer mce.mu.Unlock()
   213  	return mce.routineMgr
   214  }
   215  
   216  var RecordStatement = func(ctx context.Context, ses *Session, proc *process.Process, cw ComputationWrapper, envBegin time.Time, envStmt string, useEnv bool) context.Context {
   217  	if !motrace.GetTracerProvider().IsEnable() {
   218  		return ctx
   219  	}
   220  	sessInfo := proc.SessionInfo
   221  	tenant := ses.GetTenantInfo()
   222  	if tenant == nil {
   223  		tenant, _ = GetTenantInfo(ctx, "internal")
   224  	}
   225  	var txnID uuid.UUID
   226  	var txn TxnOperator
   227  	var err error
   228  	if handler := ses.GetTxnHandler(); handler.IsValidTxn() {
   229  		txn, err = handler.GetTxn()
   230  		if err != nil {
   231  			logutil.Errorf("RecordStatement. error:%v", err)
   232  		} else {
   233  			copy(txnID[:], txn.Txn().ID)
   234  		}
   235  	}
   236  	var sesID uuid.UUID
   237  	copy(sesID[:], ses.GetUUID())
   238  	requestAt := envBegin
   239  	if !useEnv {
   240  		requestAt = time.Now()
   241  	}
   242  	var stmID uuid.UUID
   243  	var statement tree.Statement = nil
   244  	var text string
   245  	if cw != nil {
   246  		copy(stmID[:], cw.GetUUID())
   247  		statement = cw.GetAst()
   248  		ses.ast = statement
   249  		fmtCtx := tree.NewFmtCtx(dialect.MYSQL, tree.WithQuoteString(true))
   250  		statement.Format(fmtCtx)
   251  		text = SubStringFromBegin(fmtCtx.String(), int(ses.GetParameterUnit().SV.LengthOfQueryPrinted))
   252  	} else {
   253  		stmID = uuid.New()
   254  		text = SubStringFromBegin(envStmt, int(ses.GetParameterUnit().SV.LengthOfQueryPrinted))
   255  	}
   256  	stm := &motrace.StatementInfo{
   257  		StatementID:          stmID,
   258  		TransactionID:        txnID,
   259  		SessionID:            sesID,
   260  		Account:              tenant.GetTenant(),
   261  		RoleId:               proc.SessionInfo.RoleId,
   262  		User:                 tenant.GetUser(),
   263  		Host:                 sessInfo.GetHost(),
   264  		Database:             ses.GetDatabaseName(),
   265  		Statement:            text,
   266  		StatementFingerprint: "", // fixme: (Reserved)
   267  		StatementTag:         "", // fixme: (Reserved)
   268  		SqlSourceType:        ses.sqlSourceType,
   269  		RequestAt:            requestAt,
   270  		StatementType:        getStatementType(statement).GetStatementType(),
   271  		QueryType:            getStatementType(statement).GetQueryType(),
   272  	}
   273  	if ses.sqlSourceType != "internal_sql" {
   274  		ses.tStmt = stm
   275  		ses.pushQueryId(types.Uuid(stmID).ToString())
   276  	}
   277  	if !stm.IsZeroTxnID() {
   278  		stm.Report(ctx)
   279  	}
   280  	sc := trace.SpanContextWithID(trace.TraceID(stmID), trace.SpanKindStatement)
   281  	proc.WithSpanContext(sc)
   282  	reqCtx := ses.GetRequestContext()
   283  	ses.SetRequestContext(trace.ContextWithSpanContext(reqCtx, sc))
   284  	return motrace.ContextWithStatement(trace.ContextWithSpanContext(ctx, sc), stm)
   285  }
   286  
   287  var RecordParseErrorStatement = func(ctx context.Context, ses *Session, proc *process.Process, envBegin time.Time, envStmt string) context.Context {
   288  	ctx = RecordStatement(ctx, ses, proc, nil, envBegin, envStmt, true)
   289  	tenant := ses.GetTenantInfo()
   290  	if tenant == nil {
   291  		tenant, _ = GetTenantInfo(ctx, "internal")
   292  	}
   293  	incStatementCounter(tenant.GetTenant(), nil)
   294  	incStatementErrorsCounter(tenant.GetTenant(), nil)
   295  	return ctx
   296  }
   297  
   298  // RecordStatementTxnID record txnID after TxnBegin or Compile(autocommit=1)
   299  var RecordStatementTxnID = func(ctx context.Context, ses *Session) {
   300  	var err error
   301  	var txn TxnOperator
   302  	if stm := motrace.StatementFromContext(ctx); ses != nil && stm != nil && stm.IsZeroTxnID() {
   303  		if handler := ses.GetTxnHandler(); handler.IsValidTxn() {
   304  			txn, err = handler.GetTxn()
   305  			if err != nil {
   306  				logutil.Errorf("RecordStatementTxnID. error:%v", err)
   307  			} else {
   308  				stm.SetTxnID(txn.Txn().ID)
   309  			}
   310  
   311  		}
   312  		stm.Report(ctx)
   313  	}
   314  }
   315  
   316  // outputPool outputs the data
   317  type outputPool interface {
   318  	resetLineStr()
   319  
   320  	reset()
   321  
   322  	getEmptyRow() ([]interface{}, error)
   323  
   324  	flush() error
   325  }
   326  
   327  var _ outputPool = &outputQueue{}
   328  var _ outputPool = &fakeOutputQueue{}
   329  
   330  type outputQueue struct {
   331  	ctx          context.Context
   332  	proto        MysqlProtocol
   333  	mrs          *MysqlResultSet
   334  	rowIdx       uint64
   335  	length       uint64
   336  	ep           *ExportParam
   337  	lineStr      []byte
   338  	showStmtType ShowStatementType
   339  
   340  	getEmptyRowTime time.Duration
   341  	flushTime       time.Duration
   342  }
   343  
   344  func (o *outputQueue) resetLineStr() {
   345  	o.lineStr = o.lineStr[:0]
   346  }
   347  
   348  func NewOutputQueue(ctx context.Context, proto MysqlProtocol, mrs *MysqlResultSet, length uint64, ep *ExportParam, showStatementType ShowStatementType) *outputQueue {
   349  	return &outputQueue{
   350  		ctx:          ctx,
   351  		proto:        proto,
   352  		mrs:          mrs,
   353  		rowIdx:       0,
   354  		length:       length,
   355  		ep:           ep,
   356  		showStmtType: showStatementType,
   357  	}
   358  }
   359  
   360  func (o *outputQueue) reset() {
   361  	o.getEmptyRowTime = 0
   362  	o.flushTime = 0
   363  }
   364  
   365  /*
   366  getEmptyRow returns a empty space for filling data.
   367  If there is no space, it flushes the data into the protocol
   368  and returns an empty space then.
   369  */
   370  func (o *outputQueue) getEmptyRow() ([]interface{}, error) {
   371  	if o.rowIdx >= o.length {
   372  		if err := o.flush(); err != nil {
   373  			return nil, err
   374  		}
   375  	}
   376  
   377  	row := o.mrs.Data[o.rowIdx]
   378  	o.rowIdx++
   379  	return row, nil
   380  }
   381  
   382  /*
   383  flush will force the data flushed into the protocol.
   384  */
   385  func (o *outputQueue) flush() error {
   386  	if o.rowIdx <= 0 {
   387  		return nil
   388  	}
   389  	if o.ep.Outfile {
   390  		if err := exportDataToCSVFile(o); err != nil {
   391  			logutil.Errorf("export to csv file error %v", err)
   392  			return err
   393  		}
   394  	} else {
   395  		//send group of row
   396  		if o.showStmtType == ShowColumns || o.showStmtType == ShowTableStatus {
   397  			o.rowIdx = 0
   398  			return nil
   399  		}
   400  
   401  		if err := o.proto.SendResultSetTextBatchRowSpeedup(o.mrs, o.rowIdx); err != nil {
   402  			logutil.Errorf("flush error %v", err)
   403  			return err
   404  		}
   405  	}
   406  	o.rowIdx = 0
   407  	return nil
   408  }
   409  
   410  // fakeOutputQueue saves the data into the session.
   411  type fakeOutputQueue struct {
   412  	mrs *MysqlResultSet
   413  }
   414  
   415  func newFakeOutputQueue(mrs *MysqlResultSet) outputPool {
   416  	return &fakeOutputQueue{mrs: mrs}
   417  }
   418  
   419  func (foq *fakeOutputQueue) resetLineStr() {}
   420  
   421  func (foq *fakeOutputQueue) reset() {}
   422  
   423  func (foq *fakeOutputQueue) getEmptyRow() ([]interface{}, error) {
   424  	row := make([]interface{}, foq.mrs.GetColumnCount())
   425  	foq.mrs.AddRow(row)
   426  	return row, nil
   427  }
   428  
   429  func (foq *fakeOutputQueue) flush() error {
   430  	return nil
   431  }
   432  
   433  const (
   434  	primaryKeyPos = 25
   435  )
   436  
   437  /*
   438  handle show columns from table in plan2 and tae
   439  */
   440  func handleShowColumns(ses *Session, stmt *tree.ShowColumns) error {
   441  	data := ses.GetData()
   442  	mrs := ses.GetMysqlResultSet()
   443  	dbName := stmt.Table.GetDBName()
   444  	if len(dbName) == 0 {
   445  		dbName = ses.GetDatabaseName()
   446  	}
   447  
   448  	tableName := string(stmt.Table.ToTableName().ObjectName)
   449  	ctx := ses.GetTxnCompileCtx()
   450  	_, tableDef := ctx.Resolve(dbName, tableName)
   451  	if tableDef == nil {
   452  		return moerr.NewNoSuchTable(ctx.GetContext(), dbName, tableName)
   453  	}
   454  
   455  	colNameToColContent := make(map[string][]interface{})
   456  	for _, d := range data {
   457  		colName := string(d[0].([]byte))
   458  		if colName == catalog.Row_ID {
   459  			continue
   460  		}
   461  		//the non-sys account skips the column account_id of the cluster table
   462  		if util.IsClusterTableAttribute(colName) &&
   463  			isClusterTable(dbName, tableName) &&
   464  			ses.GetTenantInfo() != nil &&
   465  			!ses.GetTenantInfo().IsSysTenant() {
   466  			continue
   467  		}
   468  
   469  		if len(d) == 7 {
   470  			row := make([]interface{}, 7)
   471  			row[0] = colName
   472  			typ := &types.Type{}
   473  			data := d[1].([]uint8)
   474  			if err := types.Decode(data, typ); err != nil {
   475  				return err
   476  			}
   477  			row[1] = typ.DescString()
   478  			row[2] = d[2]
   479  			row[3] = d[3]
   480  			if value, ok := row[3].([]uint8); ok {
   481  				if len(value) != 0 {
   482  					row[2] = "NO"
   483  				}
   484  			}
   485  			def := &plan.Default{}
   486  			defaultData := d[4].([]uint8)
   487  			if string(defaultData) == "" {
   488  				row[4] = "NULL"
   489  			} else {
   490  				if err := types.Decode(defaultData, def); err != nil {
   491  					return err
   492  				}
   493  				originString := def.GetOriginString()
   494  				switch originString {
   495  				case "uuid()":
   496  					row[4] = "UUID"
   497  				case "current_timestamp()":
   498  					row[4] = "CURRENT_TIMESTAMP"
   499  				case "now()":
   500  					row[4] = "CURRENT_TIMESTAMP"
   501  				case "":
   502  					row[4] = "NULL"
   503  				default:
   504  					row[4] = originString
   505  				}
   506  			}
   507  
   508  			row[5] = ""
   509  			row[6] = d[6]
   510  			colNameToColContent[colName] = row
   511  		} else {
   512  			row := make([]interface{}, 9)
   513  			row[0] = colName
   514  			typ := &types.Type{}
   515  			data := d[1].([]uint8)
   516  			if err := types.Decode(data, typ); err != nil {
   517  				return err
   518  			}
   519  			row[1] = typ.DescString()
   520  			row[2] = "NULL"
   521  			row[3] = d[3]
   522  			row[4] = d[4]
   523  			if value, ok := row[4].([]uint8); ok {
   524  				if len(value) != 0 {
   525  					row[3] = "NO"
   526  				}
   527  			}
   528  			def := &plan.Default{}
   529  			defaultData := d[5].([]uint8)
   530  			if string(defaultData) == "" {
   531  				row[5] = "NULL"
   532  			} else {
   533  				if err := types.Decode(defaultData, def); err != nil {
   534  					return err
   535  				}
   536  				originString := def.GetOriginString()
   537  				switch originString {
   538  				case "uuid()":
   539  					row[5] = "UUID"
   540  				case "current_timestamp()":
   541  					row[5] = "CURRENT_TIMESTAMP"
   542  				case "now()":
   543  					row[5] = "CURRENT_TIMESTAMP"
   544  				case "":
   545  					row[5] = "NULL"
   546  				default:
   547  					row[5] = originString
   548  				}
   549  			}
   550  
   551  			row[6] = ""
   552  			row[7] = d[7]
   553  			row[8] = d[8]
   554  			colNameToColContent[colName] = row
   555  		}
   556  	}
   557  	for _, col := range tableDef.Cols {
   558  		if row, ok := colNameToColContent[col.Name]; ok {
   559  			mrs.AddRow(row)
   560  		}
   561  
   562  	}
   563  	if err := ses.GetMysqlProtocol().SendResultSetTextBatchRowSpeedup(mrs, mrs.GetRowCount()); err != nil {
   564  		logErrorf(ses.GetConciseProfile(), "handleShowColumns error %v", err)
   565  		return err
   566  	}
   567  	return nil
   568  }
   569  
   570  func handleShowTableStatus(ses *Session, stmt *tree.ShowTableStatus, proc *process.Process) error {
   571  	db, err := ses.GetStorage().Database(ses.requestCtx, stmt.DbName, proc.TxnOperator)
   572  	if err != nil {
   573  		return err
   574  	}
   575  	mrs := ses.GetMysqlResultSet()
   576  	for _, row := range ses.data {
   577  		tableName := string(row[0].([]byte))
   578  		r, err := db.Relation(ses.requestCtx, tableName)
   579  		if err != nil {
   580  			return err
   581  		}
   582  		_, err = r.Ranges(ses.requestCtx, nil)
   583  		if err != nil {
   584  			return err
   585  		}
   586  		row[3], err = r.Rows(ses.requestCtx)
   587  		if err != nil {
   588  			return err
   589  		}
   590  		mrs.AddRow(row)
   591  	}
   592  	if err := ses.GetMysqlProtocol().SendResultSetTextBatchRowSpeedup(mrs, mrs.GetRowCount()); err != nil {
   593  		logErrorf(ses.GetConciseProfile(), "handleShowTableStatus error %v", err)
   594  		return err
   595  	}
   596  	return nil
   597  }
   598  
   599  /*
   600  extract the data from the pipeline.
   601  obj: routine obj
   602  TODO:Add error
   603  Warning: The pipeline is the multi-thread environment. The getDataFromPipeline will
   604  
   605  	access the shared data. Be careful when it writes the shared data.
   606  */
   607  func getDataFromPipeline(obj interface{}, bat *batch.Batch) error {
   608  	ses := obj.(*Session)
   609  	if openSaveQueryResult(ses) {
   610  		if bat == nil {
   611  			if err := saveQueryResultMeta(ses); err != nil {
   612  				return err
   613  			}
   614  		} else {
   615  			if err := saveQueryResult(ses, bat); err != nil {
   616  				return err
   617  			}
   618  		}
   619  	}
   620  	if bat == nil {
   621  		return nil
   622  	}
   623  
   624  	begin := time.Now()
   625  
   626  	proto := ses.GetMysqlProtocol()
   627  	proto.ResetStatistics()
   628  
   629  	//Create a new temporary resultset per pipeline thread.
   630  	mrs := &MysqlResultSet{}
   631  	//Warning: Don't change ResultColumns in this.
   632  	//Reference the shared ResultColumns of the session among multi-thread.
   633  	sesMrs := ses.GetMysqlResultSet()
   634  	mrs.Columns = sesMrs.Columns
   635  	mrs.Name2Index = sesMrs.Name2Index
   636  
   637  	begin3 := time.Now()
   638  	countOfResultSet := 1
   639  	//group row
   640  	mrs.Data = make([][]interface{}, countOfResultSet)
   641  	for i := 0; i < countOfResultSet; i++ {
   642  		mrs.Data[i] = make([]interface{}, len(bat.Vecs))
   643  	}
   644  	allocateOutBufferTime := time.Since(begin3)
   645  
   646  	oq := NewOutputQueue(ses.GetRequestContext(), proto, mrs, uint64(countOfResultSet), ses.GetExportParam(), ses.GetShowStmtType())
   647  	oq.reset()
   648  
   649  	row2colTime := time.Duration(0)
   650  
   651  	procBatchBegin := time.Now()
   652  
   653  	n := vector.Length(bat.Vecs[0])
   654  
   655  	requestCtx := ses.GetRequestContext()
   656  	for j := 0; j < n; j++ { //row index
   657  		if oq.ep.Outfile {
   658  			select {
   659  			case <-requestCtx.Done():
   660  				{
   661  					return nil
   662  				}
   663  			default:
   664  				{
   665  				}
   666  			}
   667  		}
   668  
   669  		if bat.Zs[j] <= 0 {
   670  			continue
   671  		}
   672  		row, err := extractRowFromEveryVector(ses, bat, int64(j), oq)
   673  		if err != nil {
   674  			return err
   675  		}
   676  		if oq.showStmtType == ShowColumns || oq.showStmtType == ShowTableStatus {
   677  			row2 := make([]interface{}, len(row))
   678  			copy(row2, row)
   679  			ses.AppendData(row2)
   680  		}
   681  	}
   682  
   683  	//logutil.Debugf("row group -+> %v ", oq.getData())
   684  
   685  	err := oq.flush()
   686  	if err != nil {
   687  		return err
   688  	}
   689  
   690  	procBatchTime := time.Since(procBatchBegin)
   691  	tTime := time.Since(begin)
   692  	logInfof(ses.GetConciseProfile(), "rowCount %v \n"+
   693  		"time of getDataFromPipeline : %s \n"+
   694  		"processBatchTime %v \n"+
   695  		"row2colTime %v \n"+
   696  		"allocateOutBufferTime %v \n"+
   697  		"outputQueue.flushTime %v \n"+
   698  		"processBatchTime - row2colTime - allocateOutbufferTime - flushTime %v \n"+
   699  		"restTime(=tTime - row2colTime - allocateOutBufferTime) %v \n"+
   700  		"protoStats %s",
   701  		n,
   702  		tTime,
   703  		procBatchTime,
   704  		row2colTime,
   705  		allocateOutBufferTime,
   706  		oq.flushTime,
   707  		procBatchTime-row2colTime-allocateOutBufferTime-oq.flushTime,
   708  		tTime-row2colTime-allocateOutBufferTime,
   709  		proto.GetStats())
   710  
   711  	return nil
   712  }
   713  
   714  // extractRowFromEveryVector gets the j row from the every vector and outputs the row
   715  func extractRowFromEveryVector(ses *Session, dataSet *batch.Batch, j int64, oq outputPool) ([]interface{}, error) {
   716  	row, err := oq.getEmptyRow()
   717  	if err != nil {
   718  		return nil, err
   719  	}
   720  	var rowIndex = int64(j)
   721  	for i, vec := range dataSet.Vecs { //col index
   722  		rowIndexBackup := rowIndex
   723  		if vec.IsScalarNull() {
   724  			row[i] = nil
   725  			continue
   726  		}
   727  		if vec.IsScalar() {
   728  			rowIndex = 0
   729  		}
   730  
   731  		err = extractRowFromVector(ses, vec, i, row, rowIndex)
   732  		if err != nil {
   733  			return nil, err
   734  		}
   735  		rowIndex = rowIndexBackup
   736  	}
   737  	//duplicate rows
   738  	for i := int64(0); i < dataSet.Zs[j]-1; i++ {
   739  		erow, rr := oq.getEmptyRow()
   740  		if rr != nil {
   741  			return nil, rr
   742  		}
   743  		for l := 0; l < len(dataSet.Vecs); l++ {
   744  			erow[l] = row[l]
   745  		}
   746  	}
   747  	return row, nil
   748  }
   749  
   750  func formatFloatNum[T types.Floats](num T, Typ types.Type) T {
   751  	if Typ.Precision == -1 || Typ.Width == 0 {
   752  		return num
   753  	}
   754  	pow := math.Pow10(int(Typ.Precision))
   755  	t := math.Abs(float64(num))
   756  	upperLimit := math.Pow10(int(Typ.Width))
   757  	if t >= upperLimit {
   758  		t = upperLimit - 1
   759  	} else {
   760  		t *= pow
   761  		t = math.Round(t)
   762  	}
   763  	if t >= upperLimit {
   764  		t = upperLimit - 1
   765  	}
   766  	t /= pow
   767  	if num < 0 {
   768  		t = -1 * t
   769  	}
   770  	return T(t)
   771  }
   772  
   773  // extractRowFromVector gets the rowIndex row from the i vector
   774  func extractRowFromVector(ses *Session, vec *vector.Vector, i int, row []interface{}, rowIndex int64) error {
   775  	timeZone := ses.GetTimeZone()
   776  	switch vec.Typ.Oid { //get col
   777  	case types.T_json:
   778  		if !nulls.Any(vec.Nsp) {
   779  			row[i] = types.DecodeJson(vec.GetBytes(rowIndex))
   780  		} else {
   781  			if nulls.Contains(vec.Nsp, uint64(rowIndex)) {
   782  				row[i] = nil
   783  			} else {
   784  				row[i] = types.DecodeJson(vec.GetBytes(rowIndex))
   785  			}
   786  		}
   787  	case types.T_bool:
   788  		if !nulls.Any(vec.Nsp) { //all data in this column are not null
   789  			vs := vec.Col.([]bool)
   790  			row[i] = vs[rowIndex]
   791  		} else {
   792  			if nulls.Contains(vec.Nsp, uint64(rowIndex)) { //is null
   793  				row[i] = nil
   794  			} else {
   795  				vs := vec.Col.([]bool)
   796  				row[i] = vs[rowIndex]
   797  			}
   798  		}
   799  	case types.T_int8:
   800  		if !nulls.Any(vec.Nsp) { //all data in this column are not null
   801  			vs := vec.Col.([]int8)
   802  			row[i] = vs[rowIndex]
   803  		} else {
   804  			if nulls.Contains(vec.Nsp, uint64(rowIndex)) { //is null
   805  				row[i] = nil
   806  			} else {
   807  				vs := vec.Col.([]int8)
   808  				row[i] = vs[rowIndex]
   809  			}
   810  		}
   811  	case types.T_uint8:
   812  		if !nulls.Any(vec.Nsp) { //all data in this column are not null
   813  			vs := vec.Col.([]uint8)
   814  			row[i] = vs[rowIndex]
   815  		} else {
   816  			if nulls.Contains(vec.Nsp, uint64(rowIndex)) { //is null
   817  				row[i] = nil
   818  			} else {
   819  				vs := vec.Col.([]uint8)
   820  				row[i] = vs[rowIndex]
   821  			}
   822  		}
   823  	case types.T_int16:
   824  		if !nulls.Any(vec.Nsp) { //all data in this column are not null
   825  			vs := vec.Col.([]int16)
   826  			row[i] = vs[rowIndex]
   827  		} else {
   828  			if nulls.Contains(vec.Nsp, uint64(rowIndex)) { //is null
   829  				row[i] = nil
   830  			} else {
   831  				vs := vec.Col.([]int16)
   832  				row[i] = vs[rowIndex]
   833  			}
   834  		}
   835  	case types.T_uint16:
   836  		if !nulls.Any(vec.Nsp) { //all data in this column are not null
   837  			vs := vec.Col.([]uint16)
   838  			row[i] = vs[rowIndex]
   839  		} else {
   840  			if nulls.Contains(vec.Nsp, uint64(rowIndex)) { //is null
   841  				row[i] = nil
   842  			} else {
   843  				vs := vec.Col.([]uint16)
   844  				row[i] = vs[rowIndex]
   845  			}
   846  		}
   847  	case types.T_int32:
   848  		if !nulls.Any(vec.Nsp) { //all data in this column are not null
   849  			vs := vec.Col.([]int32)
   850  			row[i] = vs[rowIndex]
   851  		} else {
   852  			if nulls.Contains(vec.Nsp, uint64(rowIndex)) { //is null
   853  				row[i] = nil
   854  			} else {
   855  				vs := vec.Col.([]int32)
   856  				row[i] = vs[rowIndex]
   857  			}
   858  		}
   859  	case types.T_uint32:
   860  		if !nulls.Any(vec.Nsp) { //all data in this column are not null
   861  			vs := vec.Col.([]uint32)
   862  			row[i] = vs[rowIndex]
   863  		} else {
   864  			if nulls.Contains(vec.Nsp, uint64(rowIndex)) { //is null
   865  				row[i] = nil
   866  			} else {
   867  				vs := vec.Col.([]uint32)
   868  				row[i] = vs[rowIndex]
   869  			}
   870  		}
   871  	case types.T_int64:
   872  		if !nulls.Any(vec.Nsp) { //all data in this column are not null
   873  			vs := vec.Col.([]int64)
   874  			row[i] = vs[rowIndex]
   875  		} else {
   876  			if nulls.Contains(vec.Nsp, uint64(rowIndex)) { //is null
   877  				row[i] = nil
   878  			} else {
   879  				vs := vec.Col.([]int64)
   880  				row[i] = vs[rowIndex]
   881  			}
   882  		}
   883  	case types.T_uint64:
   884  		if !nulls.Any(vec.Nsp) { //all data in this column are not null
   885  			vs := vec.Col.([]uint64)
   886  			row[i] = vs[rowIndex]
   887  		} else {
   888  			if nulls.Contains(vec.Nsp, uint64(rowIndex)) { //is null
   889  				row[i] = nil
   890  			} else {
   891  				vs := vec.Col.([]uint64)
   892  				row[i] = vs[rowIndex]
   893  			}
   894  		}
   895  	case types.T_float32:
   896  		if !nulls.Any(vec.Nsp) { //all data in this column are not null
   897  			vs := vec.Col.([]float32)
   898  			row[i] = formatFloatNum(vs[rowIndex], vec.Typ)
   899  		} else {
   900  			if nulls.Contains(vec.Nsp, uint64(rowIndex)) { //is null
   901  				row[i] = nil
   902  			} else {
   903  				vs := vec.Col.([]float32)
   904  				row[i] = formatFloatNum(vs[rowIndex], vec.Typ)
   905  			}
   906  		}
   907  	case types.T_float64:
   908  		if !nulls.Any(vec.Nsp) { //all data in this column are not null
   909  			vs := vec.Col.([]float64)
   910  			row[i] = formatFloatNum(vs[rowIndex], vec.Typ)
   911  		} else {
   912  			if nulls.Contains(vec.Nsp, uint64(rowIndex)) { //is null
   913  				row[i] = nil
   914  			} else {
   915  				vs := vec.Col.([]float64)
   916  				row[i] = formatFloatNum(vs[rowIndex], vec.Typ)
   917  			}
   918  		}
   919  	case types.T_char, types.T_varchar, types.T_blob, types.T_text:
   920  		if !nulls.Any(vec.Nsp) { //all data in this column are not null
   921  			row[i] = vec.GetBytes(rowIndex)
   922  		} else {
   923  			if nulls.Contains(vec.Nsp, uint64(rowIndex)) { //is null
   924  				row[i] = nil
   925  			} else {
   926  				row[i] = vec.GetBytes(rowIndex)
   927  			}
   928  		}
   929  	case types.T_date:
   930  		if !nulls.Any(vec.Nsp) { //all data in this column are not null
   931  			vs := vec.Col.([]types.Date)
   932  			row[i] = vs[rowIndex]
   933  		} else {
   934  			if nulls.Contains(vec.Nsp, uint64(rowIndex)) { //is null
   935  				row[i] = nil
   936  			} else {
   937  				vs := vec.Col.([]types.Date)
   938  				row[i] = vs[rowIndex]
   939  			}
   940  		}
   941  	case types.T_datetime:
   942  		precision := vec.Typ.Precision
   943  		if !nulls.Any(vec.Nsp) { //all data in this column are not null
   944  			vs := vec.Col.([]types.Datetime)
   945  			row[i] = vs[rowIndex].String2(precision)
   946  		} else {
   947  			if nulls.Contains(vec.Nsp, uint64(rowIndex)) { //is null
   948  				row[i] = nil
   949  			} else {
   950  				vs := vec.Col.([]types.Datetime)
   951  				row[i] = vs[rowIndex].String2(precision)
   952  			}
   953  		}
   954  	case types.T_time:
   955  		precision := vec.Typ.Precision
   956  		if !nulls.Any(vec.Nsp) { //all data in this column are not null
   957  			vs := vec.Col.([]types.Time)
   958  			row[i] = vs[rowIndex].String2(precision)
   959  		} else {
   960  			if nulls.Contains(vec.Nsp, uint64(rowIndex)) { //is null
   961  				row[i] = nil
   962  			} else {
   963  				vs := vec.Col.([]types.Time)
   964  				row[i] = vs[rowIndex].String2(precision)
   965  			}
   966  		}
   967  	case types.T_timestamp:
   968  		precision := vec.Typ.Precision
   969  		if !nulls.Any(vec.Nsp) { //all data in this column are not null
   970  			vs := vec.Col.([]types.Timestamp)
   971  			row[i] = vs[rowIndex].String2(timeZone, precision)
   972  		} else {
   973  			if nulls.Contains(vec.Nsp, uint64(rowIndex)) { //is null
   974  				row[i] = nil
   975  			} else {
   976  				vs := vec.Col.([]types.Timestamp)
   977  				row[i] = vs[rowIndex].String2(timeZone, precision)
   978  			}
   979  		}
   980  	case types.T_decimal64:
   981  		scale := vec.Typ.Scale
   982  		if !nulls.Any(vec.Nsp) { //all data in this column are not null
   983  			vs := vec.Col.([]types.Decimal64)
   984  			row[i] = vs[rowIndex].ToStringWithScale(scale)
   985  		} else {
   986  			if nulls.Contains(vec.Nsp, uint64(rowIndex)) {
   987  				row[i] = nil
   988  			} else {
   989  				vs := vec.Col.([]types.Decimal64)
   990  				row[i] = vs[rowIndex].ToStringWithScale(scale)
   991  			}
   992  		}
   993  	case types.T_decimal128:
   994  		scale := vec.Typ.Scale
   995  		if !nulls.Any(vec.Nsp) { //all data in this column are not null
   996  			vs := vec.Col.([]types.Decimal128)
   997  			row[i] = vs[rowIndex].ToStringWithScale(scale)
   998  		} else {
   999  			if nulls.Contains(vec.Nsp, uint64(rowIndex)) {
  1000  				row[i] = nil
  1001  			} else {
  1002  				vs := vec.Col.([]types.Decimal128)
  1003  				row[i] = vs[rowIndex].ToStringWithScale(scale)
  1004  			}
  1005  		}
  1006  	case types.T_uuid:
  1007  		if !nulls.Any(vec.Nsp) {
  1008  			vs := vec.Col.([]types.Uuid)
  1009  			row[i] = vs[rowIndex].ToString()
  1010  		} else {
  1011  			if nulls.Contains(vec.Nsp, uint64(rowIndex)) { //is null
  1012  				row[i] = nil
  1013  			} else {
  1014  				vs := vec.Col.([]types.Uuid)
  1015  				row[i] = vs[rowIndex].ToString()
  1016  			}
  1017  		}
  1018  	case types.T_Rowid:
  1019  		if !nulls.Any(vec.Nsp) {
  1020  			vs := vec.Col.([]types.Rowid)
  1021  			row[i] = vs[rowIndex]
  1022  		} else {
  1023  			if nulls.Contains(vec.Nsp, uint64(rowIndex)) { //is null
  1024  				row[i] = nil
  1025  			} else {
  1026  				vs := vec.Col.([]types.Rowid)
  1027  				row[i] = vs[rowIndex]
  1028  			}
  1029  		}
  1030  	default:
  1031  		logErrorf(ses.GetConciseProfile(), "extractRowFromVector : unsupported type %d", vec.Typ.Oid)
  1032  		return moerr.NewInternalError(ses.requestCtx, "extractRowFromVector : unsupported type %d", vec.Typ.Oid)
  1033  	}
  1034  	return nil
  1035  }
  1036  
  1037  func doUse(ctx context.Context, ses *Session, db string) error {
  1038  	txnHandler := ses.GetTxnHandler()
  1039  	var txn TxnOperator
  1040  	var err error
  1041  	txn, err = txnHandler.GetTxn()
  1042  	if err != nil {
  1043  		return err
  1044  	}
  1045  	//TODO: check meta data
  1046  	if _, err = ses.GetParameterUnit().StorageEngine.Database(ctx, db, txn); err != nil {
  1047  		//echo client. no such database
  1048  		return moerr.NewBadDB(ctx, db)
  1049  	}
  1050  	oldDB := ses.GetDatabaseName()
  1051  	ses.SetDatabaseName(db)
  1052  
  1053  	logInfof(ses.GetConciseProfile(), "User %s change database from [%s] to [%s]", ses.GetUserName(), oldDB, ses.GetDatabaseName())
  1054  
  1055  	return nil
  1056  }
  1057  
  1058  func (mce *MysqlCmdExecutor) handleChangeDB(requestCtx context.Context, db string) error {
  1059  	return doUse(requestCtx, mce.GetSession(), db)
  1060  }
  1061  
  1062  func (mce *MysqlCmdExecutor) handleDump(requestCtx context.Context, dump *tree.MoDump) error {
  1063  	var err error
  1064  	if !dump.DumpDatabase {
  1065  		return doDumpQueryResult(requestCtx, mce.GetSession(), dump.ExportParams)
  1066  	}
  1067  	dump.OutFile = maybeAppendExtension(dump.OutFile)
  1068  	exists, err := fileExists(dump.OutFile)
  1069  	if exists {
  1070  		return moerr.NewFileAlreadyExists(requestCtx, dump.OutFile)
  1071  	}
  1072  	if err != nil {
  1073  		return err
  1074  	}
  1075  	if dump.MaxFileSize != 0 && dump.MaxFileSize < mpool.MB {
  1076  		return moerr.NewInvalidInput(requestCtx, "max file size must be larger than 1MB")
  1077  	}
  1078  	if len(dump.Database) == 0 {
  1079  		return moerr.NewInvalidInput(requestCtx, "No database selected")
  1080  	}
  1081  	return mce.dumpData(requestCtx, dump)
  1082  }
  1083  
  1084  func (mce *MysqlCmdExecutor) dumpData(requestCtx context.Context, dump *tree.MoDump) error {
  1085  	ses := mce.GetSession()
  1086  	txnHandler := ses.GetTxnHandler()
  1087  	bh := ses.GetBackgroundExec(requestCtx)
  1088  	defer bh.Close()
  1089  	dbName := string(dump.Database)
  1090  	var (
  1091  		db        engine.Database
  1092  		err       error
  1093  		showDbDDL = false
  1094  		dbDDL     string
  1095  		tables    []string
  1096  	)
  1097  	var txn TxnOperator
  1098  	txn, err = txnHandler.GetTxn()
  1099  	if err != nil {
  1100  		return err
  1101  	}
  1102  	if db, err = ses.GetParameterUnit().StorageEngine.Database(requestCtx, dbName, txn); err != nil {
  1103  		return moerr.NewBadDB(requestCtx, dbName)
  1104  	}
  1105  	err = bh.Exec(requestCtx, fmt.Sprintf("use `%s`", dbName))
  1106  	if err != nil {
  1107  		return err
  1108  	}
  1109  	if len(dump.Tables) == 0 {
  1110  		dbDDL = fmt.Sprintf("DROP DATABASE IF EXISTS `%s`;\n", dbName)
  1111  		createSql, err := getDDL(bh, requestCtx, fmt.Sprintf("SHOW CREATE DATABASE `%s`;", dbName))
  1112  		if err != nil {
  1113  			return err
  1114  		}
  1115  		dbDDL += createSql + "\n\nUSE `" + dbName + "`;\n\n"
  1116  		showDbDDL = true
  1117  		tables, err = db.Relations(requestCtx)
  1118  		if err != nil {
  1119  			return err
  1120  		}
  1121  	} else {
  1122  		tables = make([]string, len(dump.Tables))
  1123  		for i, t := range dump.Tables {
  1124  			tables[i] = string(t.ObjectName)
  1125  		}
  1126  	}
  1127  
  1128  	params := make([]*dumpTable, 0, len(tables))
  1129  	for _, tblName := range tables {
  1130  		if strings.HasPrefix(tblName, "%!%") { //skip hidden table
  1131  			continue
  1132  		}
  1133  		table, err := db.Relation(requestCtx, tblName)
  1134  		if err != nil {
  1135  			return err
  1136  		}
  1137  		tblDDL, err := getDDL(bh, requestCtx, fmt.Sprintf("SHOW CREATE TABLE `%s`;", tblName))
  1138  		if err != nil {
  1139  			return err
  1140  		}
  1141  		tableDefs, err := table.TableDefs(requestCtx)
  1142  		if err != nil {
  1143  			return err
  1144  		}
  1145  		attrs, isView, err := getAttrFromTableDef(tableDefs)
  1146  		if err != nil {
  1147  			return err
  1148  		}
  1149  		if isView {
  1150  			tblDDL = fmt.Sprintf("DROP VIEW IF EXISTS `%s`;\n", tblName) + tblDDL + "\n\n"
  1151  		} else {
  1152  			tblDDL = fmt.Sprintf("DROP TABLE IF EXISTS `%s`;\n", tblName) + tblDDL + "\n\n"
  1153  		}
  1154  		params = append(params, &dumpTable{tblName, tblDDL, table, attrs, isView})
  1155  	}
  1156  	return mce.dumpData2File(requestCtx, dump, dbDDL, params, showDbDDL)
  1157  }
  1158  
  1159  func (mce *MysqlCmdExecutor) dumpData2File(requestCtx context.Context, dump *tree.MoDump, dbDDL string, params []*dumpTable, showDbDDL bool) error {
  1160  	ses := mce.GetSession()
  1161  	var (
  1162  		err         error
  1163  		f           *os.File
  1164  		curFileSize int64 = 0
  1165  		curFileIdx  int64 = 1
  1166  		buf         *bytes.Buffer
  1167  		rbat        *batch.Batch
  1168  	)
  1169  	f, err = createDumpFile(requestCtx, dump.OutFile)
  1170  	if err != nil {
  1171  		return err
  1172  	}
  1173  	defer func() {
  1174  		if err != nil {
  1175  			if f != nil {
  1176  				f.Close()
  1177  			}
  1178  			if buf != nil {
  1179  				buf.Reset()
  1180  			}
  1181  			if rbat != nil {
  1182  				rbat.Clean(ses.mp)
  1183  			}
  1184  			removeFile(dump.OutFile, curFileIdx)
  1185  		}
  1186  	}()
  1187  	buf = new(bytes.Buffer)
  1188  	if showDbDDL {
  1189  		_, err = buf.WriteString(dbDDL)
  1190  		if err != nil {
  1191  			return err
  1192  		}
  1193  	}
  1194  	f, curFileIdx, curFileSize, err = writeDump2File(requestCtx, buf, dump, f, curFileIdx, curFileSize)
  1195  	if err != nil {
  1196  		return err
  1197  	}
  1198  	for _, param := range params {
  1199  		if param.isView {
  1200  			continue
  1201  		}
  1202  		_, err = buf.WriteString(param.ddl)
  1203  		if err != nil {
  1204  			return err
  1205  		}
  1206  		f, curFileIdx, curFileSize, err = writeDump2File(requestCtx, buf, dump, f, curFileIdx, curFileSize)
  1207  		if err != nil {
  1208  			return err
  1209  		}
  1210  		rds, err := param.rel.NewReader(requestCtx, 1, nil, nil)
  1211  		if err != nil {
  1212  			return err
  1213  		}
  1214  		for {
  1215  			bat, err := rds[0].Read(requestCtx, param.attrs, nil, ses.mp)
  1216  			if err != nil {
  1217  				return err
  1218  			}
  1219  			if bat == nil {
  1220  				break
  1221  			}
  1222  
  1223  			buf.WriteString("INSERT INTO ")
  1224  			buf.WriteString(param.name)
  1225  			buf.WriteString(" VALUES ")
  1226  			rbat, err = convertValueBat2Str(requestCtx, bat, ses.mp, ses.GetTimeZone())
  1227  			if err != nil {
  1228  				return err
  1229  			}
  1230  			for i := 0; i < rbat.Length(); i++ {
  1231  				if i != 0 {
  1232  					buf.WriteString(", ")
  1233  				}
  1234  				buf.WriteString("(")
  1235  				for j := 0; j < rbat.VectorCount(); j++ {
  1236  					if j != 0 {
  1237  						buf.WriteString(", ")
  1238  					}
  1239  					buf.WriteString(rbat.GetVector(int32(j)).GetString(int64(i)))
  1240  				}
  1241  				buf.WriteString(")")
  1242  			}
  1243  			buf.WriteString(";\n")
  1244  			f, curFileIdx, curFileSize, err = writeDump2File(requestCtx, buf, dump, f, curFileIdx, curFileSize)
  1245  			if err != nil {
  1246  				return err
  1247  			}
  1248  		}
  1249  		buf.WriteString("\n\n\n")
  1250  	}
  1251  	if !showDbDDL {
  1252  		return nil
  1253  	}
  1254  	for _, param := range params {
  1255  		if !param.isView {
  1256  			continue
  1257  		}
  1258  		_, err = buf.WriteString(param.ddl)
  1259  		if err != nil {
  1260  			return err
  1261  		}
  1262  		f, curFileIdx, curFileSize, err = writeDump2File(requestCtx, buf, dump, f, curFileIdx, curFileSize)
  1263  		if err != nil {
  1264  			return err
  1265  		}
  1266  	}
  1267  	return nil
  1268  }
  1269  
  1270  /*
  1271  handle "SELECT @@xxx.yyyy"
  1272  */
  1273  func (mce *MysqlCmdExecutor) handleSelectVariables(ve *tree.VarExpr) error {
  1274  	var err error = nil
  1275  	ses := mce.GetSession()
  1276  	mrs := ses.GetMysqlResultSet()
  1277  	proto := ses.GetMysqlProtocol()
  1278  
  1279  	col := new(MysqlColumn)
  1280  	col.SetColumnType(defines.MYSQL_TYPE_VARCHAR)
  1281  	col.SetName("@@" + ve.Name)
  1282  	mrs.AddColumn(col)
  1283  
  1284  	row := make([]interface{}, 1)
  1285  	if ve.System {
  1286  		if ve.Global {
  1287  			val, err := ses.GetGlobalVar(ve.Name)
  1288  			if err != nil {
  1289  				return err
  1290  			}
  1291  			row[0] = val
  1292  		} else {
  1293  			val, err := ses.GetSessionVar(ve.Name)
  1294  			if err != nil {
  1295  				return err
  1296  			}
  1297  			row[0] = val
  1298  		}
  1299  	} else {
  1300  		//user defined variable
  1301  		_, val, err := ses.GetUserDefinedVar(ve.Name)
  1302  		if err != nil {
  1303  			return err
  1304  		}
  1305  		row[0] = val
  1306  	}
  1307  
  1308  	mrs.AddRow(row)
  1309  
  1310  	mer := NewMysqlExecutionResult(0, 0, 0, 0, mrs)
  1311  	resp := NewResponse(ResultResponse, 0, int(COM_QUERY), mer)
  1312  
  1313  	if err := proto.SendResponse(ses.GetRequestContext(), resp); err != nil {
  1314  		return moerr.NewInternalError(ses.GetRequestContext(), "routine send response failed. error:%v ", err)
  1315  	}
  1316  	return err
  1317  }
  1318  
  1319  func doLoadData(requestCtx context.Context, ses *Session, proc *process.Process, load *tree.Import) (*LoadResult, error) {
  1320  	var err error
  1321  	var txn TxnOperator
  1322  	var dbHandler engine.Database
  1323  	var tableHandler engine.Relation
  1324  	proto := ses.GetMysqlProtocol()
  1325  
  1326  	logInfof(ses.GetConciseProfile(), "+++++load data")
  1327  	/*
  1328  		TODO:support LOCAL
  1329  	*/
  1330  	if load.Local {
  1331  		return nil, moerr.NewInternalError(requestCtx, "LOCAL is unsupported now")
  1332  	}
  1333  	if load.Param.Tail.Fields == nil || len(load.Param.Tail.Fields.Terminated) == 0 {
  1334  		load.Param.Tail.Fields = &tree.Fields{Terminated: ","}
  1335  	}
  1336  
  1337  	if load.Param.Tail.Fields != nil && load.Param.Tail.Fields.EscapedBy != 0 {
  1338  		return nil, moerr.NewInternalError(requestCtx, "EscapedBy field is unsupported now")
  1339  	}
  1340  
  1341  	/*
  1342  		check file
  1343  	*/
  1344  	exist, isfile, err := PathExists(load.Param.Filepath)
  1345  	if err != nil || !exist {
  1346  		return nil, moerr.NewInternalError(requestCtx, "file %s does exist. err:%v", load.Param.Filepath, err)
  1347  	}
  1348  
  1349  	if !isfile {
  1350  		return nil, moerr.NewInternalError(requestCtx, "file %s is a directory", load.Param.Filepath)
  1351  	}
  1352  
  1353  	/*
  1354  		check database
  1355  	*/
  1356  	loadDb := string(load.Table.Schema())
  1357  	loadTable := string(load.Table.Name())
  1358  	if loadDb == "" {
  1359  		if proto.GetDatabaseName() == "" {
  1360  			return nil, moerr.NewInternalError(requestCtx, "load data need database")
  1361  		}
  1362  
  1363  		//then, it uses the database name in the session
  1364  		loadDb = ses.GetDatabaseName()
  1365  	}
  1366  
  1367  	txnHandler := ses.GetTxnHandler()
  1368  	if ses.InMultiStmtTransactionMode() {
  1369  		return nil, moerr.NewInternalError(requestCtx, "do not support the Load in a transaction started by BEGIN/START TRANSACTION statement")
  1370  	}
  1371  	txn, err = txnHandler.GetTxn()
  1372  	if err != nil {
  1373  		return nil, err
  1374  	}
  1375  	dbHandler, err = ses.GetStorage().Database(requestCtx, loadDb, txn)
  1376  	if err != nil {
  1377  		//echo client. no such database
  1378  		return nil, moerr.NewBadDB(requestCtx, loadDb)
  1379  	}
  1380  
  1381  	//change db to the database in the LOAD DATA statement if necessary
  1382  	if loadDb != ses.GetDatabaseName() {
  1383  		oldDB := ses.GetDatabaseName()
  1384  		ses.SetDatabaseName(loadDb)
  1385  		logInfof(ses.GetConciseProfile(), "User %s change database from [%s] to [%s] in LOAD DATA", ses.GetUserName(), oldDB, ses.GetDatabaseName())
  1386  	}
  1387  
  1388  	/*
  1389  		check table
  1390  	*/
  1391  	if ses.IfInitedTempEngine() {
  1392  		requestCtx = context.WithValue(requestCtx, defines.TemporaryDN{}, ses.GetTempTableStorage())
  1393  	}
  1394  	tableHandler, err = dbHandler.Relation(requestCtx, loadTable)
  1395  	if err != nil {
  1396  		txn, err = ses.txnHandler.GetTxn()
  1397  		if err != nil {
  1398  			return nil, err
  1399  		}
  1400  		dbHandler, err = ses.GetStorage().Database(requestCtx, defines.TEMPORARY_DBNAME, txn)
  1401  		if err != nil {
  1402  			return nil, moerr.NewNoSuchTable(requestCtx, loadDb, loadTable)
  1403  		}
  1404  		loadTable = engine.GetTempTableName(loadDb, loadTable)
  1405  		tableHandler, err = dbHandler.Relation(requestCtx, loadTable)
  1406  		if err != nil {
  1407  			//echo client. no such table
  1408  			return nil, moerr.NewNoSuchTable(requestCtx, loadDb, loadTable)
  1409  		}
  1410  		loadDb = defines.TEMPORARY_DBNAME
  1411  		load.Table.ObjectName = tree.Identifier(loadTable)
  1412  	}
  1413  
  1414  	/*
  1415  		execute load data
  1416  	*/
  1417  	return LoadLoop(requestCtx, ses, proc, load, dbHandler, tableHandler, loadDb)
  1418  }
  1419  
  1420  /*
  1421  handle Load DataSource statement
  1422  */
  1423  func (mce *MysqlCmdExecutor) handleLoadData(requestCtx context.Context, proc *process.Process, load *tree.Import) error {
  1424  	ses := mce.GetSession()
  1425  	result, err := doLoadData(requestCtx, ses, proc, load)
  1426  	if err != nil {
  1427  		return err
  1428  	}
  1429  	/*
  1430  		response
  1431  	*/
  1432  	info := moerr.NewLoadInfo(requestCtx, result.Records, result.Deleted, result.Skipped, result.Warnings, result.WriteTimeout).Error()
  1433  	resp := NewOkResponse(result.Records, 0, uint16(result.Warnings), 0, int(COM_QUERY), info)
  1434  	if err = ses.GetMysqlProtocol().SendResponse(requestCtx, resp); err != nil {
  1435  		return moerr.NewInternalError(requestCtx, "routine send response failed. error:%v ", err)
  1436  	}
  1437  	return nil
  1438  }
  1439  
  1440  func doCmdFieldList(requestCtx context.Context, ses *Session, icfl *InternalCmdFieldList) error {
  1441  	dbName := ses.GetDatabaseName()
  1442  	if dbName == "" {
  1443  		return moerr.NewNoDB(requestCtx)
  1444  	}
  1445  
  1446  	//Get table infos for the database from the cube
  1447  	//case 1: there are no table infos for the db
  1448  	//case 2: db changed
  1449  	//NOTE: it costs too much time.
  1450  	//It just reduces the information in the auto-completion (auto-rehash) of the mysql client.
  1451  	//var attrs []ColumnInfo
  1452  	//
  1453  	//if mce.tableInfos == nil || mce.db != dbName {
  1454  	//	txnHandler := ses.GetTxnHandler()
  1455  	//	eng := ses.GetStorage()
  1456  	//	db, err := eng.Database(requestCtx, dbName, txnHandler.GetTxn())
  1457  	//	if err != nil {
  1458  	//		return err
  1459  	//	}
  1460  	//
  1461  	//	names, err := db.Relations(requestCtx)
  1462  	//	if err != nil {
  1463  	//		return err
  1464  	//	}
  1465  	//	for _, name := range names {
  1466  	//		table, err := db.Relation(requestCtx, name)
  1467  	//		if err != nil {
  1468  	//			return err
  1469  	//		}
  1470  	//
  1471  	//		defs, err := table.TableDefs(requestCtx)
  1472  	//		if err != nil {
  1473  	//			return err
  1474  	//		}
  1475  	//		for _, def := range defs {
  1476  	//			if attr, ok := def.(*engine.AttributeDef); ok {
  1477  	//				attrs = append(attrs, &engineColumnInfo{
  1478  	//					name: attr.Attr.Name,
  1479  	//					typ:  attr.Attr.Type,
  1480  	//				})
  1481  	//			}
  1482  	//		}
  1483  	//	}
  1484  	//
  1485  	//	if mce.tableInfos == nil {
  1486  	//		mce.tableInfos = make(map[string][]ColumnInfo)
  1487  	//	}
  1488  	//	mce.tableInfos[tableName] = attrs
  1489  	//}
  1490  	//
  1491  	//cols, ok := mce.tableInfos[tableName]
  1492  	//if !ok {
  1493  	//	//just give the empty info when there is no such table.
  1494  	//	attrs = make([]ColumnInfo, 0)
  1495  	//} else {
  1496  	//	attrs = cols
  1497  	//}
  1498  	//
  1499  	//for _, c := range attrs {
  1500  	//	col := new(MysqlColumn)
  1501  	//	col.SetName(c.GetName())
  1502  	//	err = convertEngineTypeToMysqlType(c.GetType(), col)
  1503  	//	if err != nil {
  1504  	//		return err
  1505  	//	}
  1506  	//
  1507  	//	/*
  1508  	//		mysql CMD_FIELD_LIST response: send the column definition per column
  1509  	//	*/
  1510  	//	err = proto.SendColumnDefinitionPacket(col, int(COM_FIELD_LIST))
  1511  	//	if err != nil {
  1512  	//		return err
  1513  	//	}
  1514  	//}
  1515  	return nil
  1516  }
  1517  
  1518  /*
  1519  handle cmd CMD_FIELD_LIST
  1520  */
  1521  func (mce *MysqlCmdExecutor) handleCmdFieldList(requestCtx context.Context, icfl *InternalCmdFieldList) error {
  1522  	var err error
  1523  	ses := mce.GetSession()
  1524  	proto := ses.GetMysqlProtocol()
  1525  
  1526  	err = doCmdFieldList(requestCtx, ses, icfl)
  1527  	if err != nil {
  1528  		return err
  1529  	}
  1530  
  1531  	/*
  1532  		mysql CMD_FIELD_LIST response: End after the column has been sent.
  1533  		send EOF packet
  1534  	*/
  1535  	err = proto.sendEOFOrOkPacket(0, 0)
  1536  	if err != nil {
  1537  		return err
  1538  	}
  1539  
  1540  	return err
  1541  }
  1542  
  1543  func doSetVar(ctx context.Context, ses *Session, sv *tree.SetVar) error {
  1544  	var err error = nil
  1545  	setVarFunc := func(system, global bool, name string, value interface{}) error {
  1546  		if system {
  1547  			if global {
  1548  				err = ses.SetGlobalVar(name, value)
  1549  				if err != nil {
  1550  					return err
  1551  				}
  1552  			} else {
  1553  				err = ses.SetSessionVar(name, value)
  1554  				if err != nil {
  1555  					return err
  1556  				}
  1557  			}
  1558  
  1559  			if strings.ToLower(name) == "autocommit" {
  1560  				svbt := SystemVariableBoolType{}
  1561  				newValue, err2 := svbt.Convert(value)
  1562  				if err2 != nil {
  1563  					return err2
  1564  				}
  1565  				err = ses.SetAutocommit(svbt.IsTrue(newValue))
  1566  				if err != nil {
  1567  					return err
  1568  				}
  1569  			}
  1570  		} else {
  1571  			err = ses.SetUserDefinedVar(name, value)
  1572  			if err != nil {
  1573  				return err
  1574  			}
  1575  		}
  1576  		return nil
  1577  	}
  1578  	for _, assign := range sv.Assignments {
  1579  		name := assign.Name
  1580  		var value interface{}
  1581  
  1582  		value, err = GetSimpleExprValue(assign.Value, ses)
  1583  		if err != nil {
  1584  			return err
  1585  		}
  1586  
  1587  		if systemVar, ok := gSysVarsDefs[name]; ok {
  1588  			if isDefault, ok := value.(bool); ok && isDefault {
  1589  				value = systemVar.Default
  1590  			}
  1591  		}
  1592  
  1593  		//TODO : fix SET NAMES after parser is ready
  1594  		if name == "names" {
  1595  			//replaced into three system variable:
  1596  			//character_set_client, character_set_connection, and character_set_results
  1597  			replacedBy := []string{
  1598  				"character_set_client", "character_set_connection", "character_set_results",
  1599  			}
  1600  			for _, rb := range replacedBy {
  1601  				err = setVarFunc(assign.System, assign.Global, rb, value)
  1602  				if err != nil {
  1603  					return err
  1604  				}
  1605  			}
  1606  		} else {
  1607  			err = setVarFunc(assign.System, assign.Global, name, value)
  1608  			if err != nil {
  1609  				return err
  1610  			}
  1611  		}
  1612  	}
  1613  	return err
  1614  }
  1615  
  1616  /*
  1617  handle setvar
  1618  */
  1619  func (mce *MysqlCmdExecutor) handleSetVar(ctx context.Context, sv *tree.SetVar) error {
  1620  	ses := mce.GetSession()
  1621  	err := doSetVar(ctx, ses, sv)
  1622  	if err != nil {
  1623  		return err
  1624  	}
  1625  
  1626  	return nil
  1627  }
  1628  
  1629  func doShowErrors(ses *Session) error {
  1630  	var err error
  1631  
  1632  	levelCol := new(MysqlColumn)
  1633  	levelCol.SetColumnType(defines.MYSQL_TYPE_VARCHAR)
  1634  	levelCol.SetName("Level")
  1635  
  1636  	CodeCol := new(MysqlColumn)
  1637  	CodeCol.SetColumnType(defines.MYSQL_TYPE_SHORT)
  1638  	CodeCol.SetName("Code")
  1639  
  1640  	MsgCol := new(MysqlColumn)
  1641  	MsgCol.SetColumnType(defines.MYSQL_TYPE_VARCHAR)
  1642  	MsgCol.SetName("Message")
  1643  
  1644  	mrs := ses.GetMysqlResultSet()
  1645  
  1646  	mrs.AddColumn(levelCol)
  1647  	mrs.AddColumn(CodeCol)
  1648  	mrs.AddColumn(MsgCol)
  1649  
  1650  	info := ses.GetErrInfo()
  1651  
  1652  	for i := info.length() - 1; i >= 0; i-- {
  1653  		row := make([]interface{}, 3)
  1654  		row[0] = "Error"
  1655  		row[1] = info.codes[i]
  1656  		row[2] = info.msgs[i]
  1657  		mrs.AddRow(row)
  1658  	}
  1659  
  1660  	return err
  1661  }
  1662  
  1663  func (mce *MysqlCmdExecutor) handleShowErrors() error {
  1664  	var err error
  1665  	ses := mce.GetSession()
  1666  	proto := ses.GetMysqlProtocol()
  1667  	err = doShowErrors(ses)
  1668  	if err != nil {
  1669  		return err
  1670  	}
  1671  
  1672  	mer := NewMysqlExecutionResult(0, 0, 0, 0, ses.GetMysqlResultSet())
  1673  	resp := NewResponse(ResultResponse, 0, int(COM_QUERY), mer)
  1674  
  1675  	if err := proto.SendResponse(ses.requestCtx, resp); err != nil {
  1676  		return moerr.NewInternalError(ses.requestCtx, "routine send response failed. error:%v ", err)
  1677  	}
  1678  	return err
  1679  }
  1680  
  1681  func doShowVariables(ses *Session, proc *process.Process, sv *tree.ShowVariables) error {
  1682  	if sv.Like != nil && sv.Where != nil {
  1683  		return moerr.NewSyntaxError(ses.GetRequestContext(), "like clause and where clause cannot exist at the same time")
  1684  	}
  1685  
  1686  	var err error = nil
  1687  
  1688  	col1 := new(MysqlColumn)
  1689  	col1.SetColumnType(defines.MYSQL_TYPE_VARCHAR)
  1690  	col1.SetName("Variable_name")
  1691  
  1692  	col2 := new(MysqlColumn)
  1693  	col2.SetColumnType(defines.MYSQL_TYPE_VARCHAR)
  1694  	col2.SetName("Value")
  1695  
  1696  	mrs := ses.GetMysqlResultSet()
  1697  	mrs.AddColumn(col1)
  1698  	mrs.AddColumn(col2)
  1699  
  1700  	var hasLike = false
  1701  	var likePattern = ""
  1702  	var isIlike = false
  1703  	if sv.Like != nil {
  1704  		hasLike = true
  1705  		if sv.Like.Op == tree.ILIKE {
  1706  			isIlike = true
  1707  		}
  1708  		likePattern = strings.ToLower(sv.Like.Right.String())
  1709  	}
  1710  
  1711  	var sysVars map[string]interface{}
  1712  	if sv.Global {
  1713  		sysVars = make(map[string]interface{})
  1714  		for k, v := range gSysVarsDefs {
  1715  			sysVars[k] = v.Default
  1716  		}
  1717  	} else {
  1718  		sysVars = ses.CopyAllSessionVars()
  1719  	}
  1720  
  1721  	rows := make([][]interface{}, 0, len(sysVars))
  1722  	for name, value := range sysVars {
  1723  		if hasLike {
  1724  			s := name
  1725  			if isIlike {
  1726  				s = strings.ToLower(s)
  1727  			}
  1728  			if !WildcardMatch(likePattern, s) {
  1729  				continue
  1730  			}
  1731  		}
  1732  		row := make([]interface{}, 2)
  1733  		row[0] = name
  1734  		gsv, ok := GSysVariables.GetDefinitionOfSysVar(name)
  1735  		if !ok {
  1736  			return moerr.NewInternalError(ses.GetRequestContext(), errorSystemVariableDoesNotExist())
  1737  		}
  1738  		row[1] = value
  1739  		if _, ok := gsv.GetType().(SystemVariableBoolType); ok {
  1740  			v, ok := value.(int8)
  1741  			if ok {
  1742  				if v == 1 {
  1743  					row[1] = "on"
  1744  				} else {
  1745  					row[1] = "off"
  1746  				}
  1747  			}
  1748  		}
  1749  		rows = append(rows, row)
  1750  	}
  1751  
  1752  	if sv.Where != nil {
  1753  		bat, err := constructVarBatch(ses, rows)
  1754  		if err != nil {
  1755  			return err
  1756  		}
  1757  		binder := plan2.NewDefaultBinder(proc.Ctx, nil, nil, &plan2.Type{Id: int32(types.T_varchar), Width: types.MaxVarcharLen}, []string{"variable_name", "value"})
  1758  		planExpr, err := binder.BindExpr(sv.Where.Expr, 0, false)
  1759  		if err != nil {
  1760  			return err
  1761  		}
  1762  
  1763  		vec, err := colexec.EvalExpr(bat, proc, planExpr)
  1764  		if err != nil {
  1765  			return err
  1766  		}
  1767  		bs := vector.GetColumn[bool](vec)
  1768  		sels := proc.Mp().GetSels()
  1769  		for i, b := range bs {
  1770  			if b {
  1771  				sels = append(sels, int64(i))
  1772  			}
  1773  		}
  1774  		bat.Shrink(sels)
  1775  		proc.Mp().PutSels(sels)
  1776  		v0 := vector.MustStrCols(bat.Vecs[0])
  1777  		v1 := vector.MustStrCols(bat.Vecs[1])
  1778  		rows = rows[:len(v0)]
  1779  		for i := range v0 {
  1780  			rows[i][0] = v0[i]
  1781  			rows[i][1] = v1[i]
  1782  		}
  1783  		bat.Clean(proc.Mp())
  1784  	}
  1785  
  1786  	//sort by name
  1787  	sort.Slice(rows, func(i, j int) bool {
  1788  		return rows[i][0].(string) < rows[j][0].(string)
  1789  	})
  1790  
  1791  	for _, row := range rows {
  1792  		mrs.AddRow(row)
  1793  	}
  1794  
  1795  	return err
  1796  }
  1797  
  1798  /*
  1799  handle show variables
  1800  */
  1801  func (mce *MysqlCmdExecutor) handleShowVariables(sv *tree.ShowVariables, proc *process.Process) error {
  1802  	ses := mce.GetSession()
  1803  	proto := ses.GetMysqlProtocol()
  1804  	err := doShowVariables(ses, proc, sv)
  1805  	if err != nil {
  1806  		return err
  1807  	}
  1808  	mer := NewMysqlExecutionResult(0, 0, 0, 0, ses.GetMysqlResultSet())
  1809  	resp := NewResponse(ResultResponse, 0, int(COM_QUERY), mer)
  1810  
  1811  	if err := proto.SendResponse(ses.requestCtx, resp); err != nil {
  1812  		return moerr.NewInternalError(ses.requestCtx, "routine send response failed. error:%v ", err)
  1813  	}
  1814  	return err
  1815  }
  1816  
  1817  func constructVarBatch(ses *Session, rows [][]interface{}) (*batch.Batch, error) {
  1818  	bat := batch.New(true, []string{"Variable_name", "Value"})
  1819  	typ := types.New(types.T_varchar, types.MaxVarcharLen, 0, 0)
  1820  	cnt := len(rows)
  1821  	bat.Zs = make([]int64, cnt)
  1822  	for i := range bat.Zs {
  1823  		bat.Zs[i] = 1
  1824  	}
  1825  	v0 := make([]string, cnt)
  1826  	v1 := make([]string, cnt)
  1827  	for i, row := range rows {
  1828  		v0[i] = row[0].(string)
  1829  		v1[i] = fmt.Sprintf("%v", row[1])
  1830  	}
  1831  	bat.Vecs[0] = vector.NewWithStrings(typ, v0, nil, ses.GetMemPool())
  1832  	bat.Vecs[1] = vector.NewWithStrings(typ, v1, nil, ses.GetMemPool())
  1833  	return bat, nil
  1834  }
  1835  
  1836  func (mce *MysqlCmdExecutor) handleAnalyzeStmt(requestCtx context.Context, stmt *tree.AnalyzeStmt) error {
  1837  	// rewrite analyzeStmt to `select approx_count_distinct(col), .. from tbl`
  1838  	// IMO, this approach is simple and future-proof
  1839  	// Although this rewriting processing could have been handled in rewrite module,
  1840  	// `handleAnalyzeStmt` can be easily managed by cron jobs in the future
  1841  	ctx := tree.NewFmtCtx(dialect.MYSQL)
  1842  	ctx.WriteString("select ")
  1843  	for i, ident := range stmt.Cols {
  1844  		if i > 0 {
  1845  			ctx.WriteByte(',')
  1846  		}
  1847  		ctx.WriteString("approx_count_distinct(")
  1848  		ctx.WriteString(string(ident))
  1849  		ctx.WriteByte(')')
  1850  	}
  1851  	ctx.WriteString(" from ")
  1852  	stmt.Table.Format(ctx)
  1853  	sql := ctx.String()
  1854  	return mce.GetDoQueryFunc()(requestCtx, sql)
  1855  }
  1856  
  1857  // Note: for pass the compile quickly. We will remove the comments in the future.
  1858  func (mce *MysqlCmdExecutor) handleExplainStmt(requestCtx context.Context, stmt *tree.ExplainStmt) error {
  1859  	es, err := getExplainOption(requestCtx, stmt.Options)
  1860  	if err != nil {
  1861  		return err
  1862  	}
  1863  
  1864  	ses := mce.GetSession()
  1865  
  1866  	switch stmt.Statement.(type) {
  1867  	case *tree.Delete:
  1868  		ses.GetTxnCompileCtx().SetQueryType(TXN_DELETE)
  1869  	case *tree.Update:
  1870  		ses.GetTxnCompileCtx().SetQueryType(TXN_UPDATE)
  1871  	default:
  1872  		ses.GetTxnCompileCtx().SetQueryType(TXN_DEFAULT)
  1873  	}
  1874  
  1875  	//get query optimizer and execute Optimize
  1876  	plan, err := buildPlan(requestCtx, ses, ses.GetTxnCompileCtx(), stmt.Statement)
  1877  	if err != nil {
  1878  		return err
  1879  	}
  1880  	if plan.GetQuery() == nil {
  1881  		return moerr.NewNotSupported(requestCtx, "the sql query plan does not support explain.")
  1882  	}
  1883  	// generator query explain
  1884  	explainQuery := explain.NewExplainQueryImpl(plan.GetQuery())
  1885  
  1886  	// build explain data buffer
  1887  	buffer := explain.NewExplainDataBuffer()
  1888  	err = explainQuery.ExplainPlan(requestCtx, buffer, es)
  1889  	if err != nil {
  1890  		return err
  1891  	}
  1892  
  1893  	protocol := ses.GetMysqlProtocol()
  1894  
  1895  	explainColName := "QUERY PLAN"
  1896  	columns, err := GetExplainColumns(requestCtx, explainColName)
  1897  	if err != nil {
  1898  		return err
  1899  	}
  1900  
  1901  	//	Step 1 : send column count and column definition.
  1902  	//send column count
  1903  	colCnt := uint64(len(columns))
  1904  	err = protocol.SendColumnCountPacket(colCnt)
  1905  	if err != nil {
  1906  		return err
  1907  	}
  1908  	//send columns
  1909  	//column_count * Protocol::ColumnDefinition packets
  1910  	cmd := ses.GetCmd()
  1911  	mrs := ses.GetMysqlResultSet()
  1912  	for _, c := range columns {
  1913  		mysqlc := c.(Column)
  1914  		mrs.AddColumn(mysqlc)
  1915  		//	mysql COM_QUERY response: send the column definition per column
  1916  		err := protocol.SendColumnDefinitionPacket(requestCtx, mysqlc, int(cmd))
  1917  		if err != nil {
  1918  			return err
  1919  		}
  1920  	}
  1921  
  1922  	//	mysql COM_QUERY response: End after the column has been sent.
  1923  	//	send EOF packet
  1924  	err = protocol.SendEOFPacketIf(0, 0)
  1925  	if err != nil {
  1926  		return err
  1927  	}
  1928  
  1929  	err = buildMoExplainQuery(explainColName, buffer, ses, getDataFromPipeline)
  1930  	if err != nil {
  1931  		return err
  1932  	}
  1933  
  1934  	err = protocol.sendEOFOrOkPacket(0, 0)
  1935  	if err != nil {
  1936  		return err
  1937  	}
  1938  	return nil
  1939  }
  1940  
  1941  func doPrepareStmt(ctx context.Context, ses *Session, st *tree.PrepareStmt) (*PrepareStmt, error) {
  1942  	switch st.Stmt.(type) {
  1943  	case *tree.Update:
  1944  		ses.GetTxnCompileCtx().SetQueryType(TXN_UPDATE)
  1945  	case *tree.Delete:
  1946  		ses.GetTxnCompileCtx().SetQueryType(TXN_DELETE)
  1947  	}
  1948  	preparePlan, err := buildPlan(ctx, ses, ses.GetTxnCompileCtx(), st)
  1949  	if err != nil {
  1950  		return nil, err
  1951  	}
  1952  
  1953  	prepareStmt := &PrepareStmt{
  1954  		Name:        preparePlan.GetDcl().GetPrepare().GetName(),
  1955  		PreparePlan: preparePlan,
  1956  		PrepareStmt: st.Stmt,
  1957  	}
  1958  
  1959  	err = ses.SetPrepareStmt(preparePlan.GetDcl().GetPrepare().GetName(), prepareStmt)
  1960  	return prepareStmt, err
  1961  }
  1962  
  1963  // handlePrepareStmt
  1964  func (mce *MysqlCmdExecutor) handlePrepareStmt(ctx context.Context, st *tree.PrepareStmt) (*PrepareStmt, error) {
  1965  	return doPrepareStmt(ctx, mce.GetSession(), st)
  1966  }
  1967  
  1968  func doPrepareString(ctx context.Context, ses *Session, st *tree.PrepareString) (*PrepareStmt, error) {
  1969  	stmts, err := mysql.Parse(ctx, st.Sql)
  1970  	if err != nil {
  1971  		return nil, err
  1972  	}
  1973  	switch stmts[0].(type) {
  1974  	case *tree.Update:
  1975  		ses.GetTxnCompileCtx().SetQueryType(TXN_UPDATE)
  1976  	case *tree.Delete:
  1977  		ses.GetTxnCompileCtx().SetQueryType(TXN_DELETE)
  1978  	}
  1979  
  1980  	preparePlan, err := buildPlan(ses.GetRequestContext(), ses, ses.GetTxnCompileCtx(), st)
  1981  	if err != nil {
  1982  		return nil, err
  1983  	}
  1984  
  1985  	prepareStmt := &PrepareStmt{
  1986  		Name:        preparePlan.GetDcl().GetPrepare().GetName(),
  1987  		PreparePlan: preparePlan,
  1988  		PrepareStmt: stmts[0],
  1989  	}
  1990  
  1991  	err = ses.SetPrepareStmt(preparePlan.GetDcl().GetPrepare().GetName(), prepareStmt)
  1992  	return prepareStmt, err
  1993  }
  1994  
  1995  // handlePrepareString
  1996  func (mce *MysqlCmdExecutor) handlePrepareString(ctx context.Context, st *tree.PrepareString) (*PrepareStmt, error) {
  1997  	return doPrepareString(ctx, mce.GetSession(), st)
  1998  }
  1999  
  2000  func doDeallocate(ctx context.Context, ses *Session, st *tree.Deallocate) error {
  2001  	deallocatePlan, err := buildPlan(ctx, ses, ses.GetTxnCompileCtx(), st)
  2002  	if err != nil {
  2003  		return err
  2004  	}
  2005  	ses.RemovePrepareStmt(deallocatePlan.GetDcl().GetDeallocate().GetName())
  2006  	return nil
  2007  }
  2008  
  2009  func doReset(ctx context.Context, ses *Session, st *tree.Reset) error {
  2010  	return nil
  2011  }
  2012  
  2013  // handleDeallocate
  2014  func (mce *MysqlCmdExecutor) handleDeallocate(ctx context.Context, st *tree.Deallocate) error {
  2015  	return doDeallocate(ctx, mce.GetSession(), st)
  2016  }
  2017  
  2018  // handleReset
  2019  func (mce *MysqlCmdExecutor) handleReset(ctx context.Context, st *tree.Reset) error {
  2020  	return doReset(ctx, mce.GetSession(), st)
  2021  }
  2022  
  2023  // handleCreateAccount creates a new user-level tenant in the context of the tenant SYS
  2024  // which has been initialized.
  2025  func (mce *MysqlCmdExecutor) handleCreateAccount(ctx context.Context, ca *tree.CreateAccount) error {
  2026  	//step1 : create new account.
  2027  	return InitGeneralTenant(ctx, mce.GetSession(), ca)
  2028  }
  2029  
  2030  // handleDropAccount drops a new user-level tenant
  2031  func (mce *MysqlCmdExecutor) handleDropAccount(ctx context.Context, da *tree.DropAccount) error {
  2032  	return doDropAccount(ctx, mce.GetSession(), da)
  2033  }
  2034  
  2035  // handleDropAccount drops a new user-level tenant
  2036  func (mce *MysqlCmdExecutor) handleAlterAccount(ctx context.Context, aa *tree.AlterAccount) error {
  2037  	return doAlterAccount(ctx, mce.GetSession(), aa)
  2038  }
  2039  
  2040  // handleAlterDatabaseConfig alter a database's mysql_compatbility_mode
  2041  func (mce *MysqlCmdExecutor) handleAlterDataBaseConfig(ctx context.Context, ad *tree.AlterDataBaseConfig) error {
  2042  	return doAlterDatabaseConfig(ctx, mce.GetSession(), ad)
  2043  }
  2044  
  2045  // handleAlterAccountConfig alter a account's mysql_compatbility_mode
  2046  func (mce *MysqlCmdExecutor) handleAlterAccountConfig(ctx context.Context, st *tree.AlterDataBaseConfig) error {
  2047  	return doAlterAccountConfig(ctx, mce.GetSession(), st)
  2048  }
  2049  
  2050  // handleCreateUser creates the user for the tenant
  2051  func (mce *MysqlCmdExecutor) handleCreateUser(ctx context.Context, cu *tree.CreateUser) error {
  2052  	ses := mce.GetSession()
  2053  	tenant := ses.GetTenantInfo()
  2054  
  2055  	//step1 : create the user
  2056  	return InitUser(ctx, ses, tenant, cu)
  2057  }
  2058  
  2059  // handleDropUser drops the user for the tenant
  2060  func (mce *MysqlCmdExecutor) handleDropUser(ctx context.Context, du *tree.DropUser) error {
  2061  	return doDropUser(ctx, mce.GetSession(), du)
  2062  }
  2063  
  2064  // handleCreateRole creates the new role
  2065  func (mce *MysqlCmdExecutor) handleCreateRole(ctx context.Context, cr *tree.CreateRole) error {
  2066  	ses := mce.GetSession()
  2067  	tenant := ses.GetTenantInfo()
  2068  
  2069  	//step1 : create the role
  2070  	return InitRole(ctx, ses, tenant, cr)
  2071  }
  2072  
  2073  // handleDropRole drops the role
  2074  func (mce *MysqlCmdExecutor) handleDropRole(ctx context.Context, dr *tree.DropRole) error {
  2075  	return doDropRole(ctx, mce.GetSession(), dr)
  2076  }
  2077  
  2078  func (mce *MysqlCmdExecutor) handleCreateFunction(ctx context.Context, cf *tree.CreateFunction) error {
  2079  	ses := mce.GetSession()
  2080  	tenant := ses.GetTenantInfo()
  2081  
  2082  	return InitFunction(ctx, ses, tenant, cf)
  2083  }
  2084  
  2085  func (mce *MysqlCmdExecutor) handleDropFunction(ctx context.Context, df *tree.DropFunction) error {
  2086  	return doDropFunction(ctx, mce.GetSession(), df)
  2087  }
  2088  
  2089  // handleGrantRole grants the role
  2090  func (mce *MysqlCmdExecutor) handleGrantRole(ctx context.Context, gr *tree.GrantRole) error {
  2091  	return doGrantRole(ctx, mce.GetSession(), gr)
  2092  }
  2093  
  2094  // handleRevokeRole revokes the role
  2095  func (mce *MysqlCmdExecutor) handleRevokeRole(ctx context.Context, rr *tree.RevokeRole) error {
  2096  	return doRevokeRole(ctx, mce.GetSession(), rr)
  2097  }
  2098  
  2099  // handleGrantRole grants the privilege to the role
  2100  func (mce *MysqlCmdExecutor) handleGrantPrivilege(ctx context.Context, gp *tree.GrantPrivilege) error {
  2101  	return doGrantPrivilege(ctx, mce.GetSession(), gp)
  2102  }
  2103  
  2104  // handleRevokePrivilege revokes the privilege from the user or role
  2105  func (mce *MysqlCmdExecutor) handleRevokePrivilege(ctx context.Context, rp *tree.RevokePrivilege) error {
  2106  	return doRevokePrivilege(ctx, mce.GetSession(), rp)
  2107  }
  2108  
  2109  // handleSwitchRole switches the role to another role
  2110  func (mce *MysqlCmdExecutor) handleSwitchRole(ctx context.Context, sr *tree.SetRole) error {
  2111  	return doSwitchRole(ctx, mce.GetSession(), sr)
  2112  }
  2113  
  2114  func doKill(ctx context.Context, rm *RoutineManager, ses *Session, k *tree.Kill) error {
  2115  	var err error
  2116  	//true: kill a connection
  2117  	//false: kill a query in a connection
  2118  	idThatKill := uint64(ses.GetConnectionID())
  2119  	if !k.Option.Exist || k.Option.Typ == tree.KillTypeConnection {
  2120  		err = rm.kill(ctx, true, idThatKill, k.ConnectionId, "")
  2121  	} else {
  2122  		err = rm.kill(ctx, false, idThatKill, k.ConnectionId, k.StmtOption.StatementId)
  2123  	}
  2124  	return err
  2125  }
  2126  
  2127  // handleKill kill a connection or query
  2128  func (mce *MysqlCmdExecutor) handleKill(ctx context.Context, k *tree.Kill) error {
  2129  	var err error
  2130  	ses := mce.GetSession()
  2131  	proto := ses.GetMysqlProtocol()
  2132  	err = doKill(ctx, mce.GetRoutineManager(), ses, k)
  2133  	if err != nil {
  2134  		return err
  2135  	}
  2136  	resp := NewGeneralOkResponse(COM_QUERY)
  2137  	if err = proto.SendResponse(ctx, resp); err != nil {
  2138  		return moerr.NewInternalError(ctx, "routine send response failed. error:%v ", err)
  2139  	}
  2140  	return err
  2141  }
  2142  
  2143  // handleShowAccounts lists the info of accounts
  2144  func (mce *MysqlCmdExecutor) handleShowAccounts(ctx context.Context, sa *tree.ShowAccounts) error {
  2145  	var err error
  2146  	ses := mce.GetSession()
  2147  	proto := ses.GetMysqlProtocol()
  2148  	err = doShowAccounts(ctx, ses, sa)
  2149  	if err != nil {
  2150  		return err
  2151  	}
  2152  	mer := NewMysqlExecutionResult(0, 0, 0, 0, ses.GetMysqlResultSet())
  2153  	resp := NewResponse(ResultResponse, 0, int(COM_QUERY), mer)
  2154  
  2155  	if err = proto.SendResponse(ctx, resp); err != nil {
  2156  		return moerr.NewInternalError(ctx, "routine send response failed. error:%v ", err)
  2157  	}
  2158  	return err
  2159  }
  2160  
  2161  func GetExplainColumns(ctx context.Context, explainColName string) ([]interface{}, error) {
  2162  	cols := []*plan2.ColDef{
  2163  		{Typ: &plan2.Type{Id: int32(types.T_varchar)}, Name: explainColName},
  2164  	}
  2165  	columns := make([]interface{}, len(cols))
  2166  	var err error = nil
  2167  	for i, col := range cols {
  2168  		c := new(MysqlColumn)
  2169  		c.SetName(col.Name)
  2170  		err = convertEngineTypeToMysqlType(ctx, types.T(col.Typ.Id), c)
  2171  		if err != nil {
  2172  			return nil, err
  2173  		}
  2174  		columns[i] = c
  2175  	}
  2176  	return columns, err
  2177  }
  2178  
  2179  func getExplainOption(requestCtx context.Context, options []tree.OptionElem) (*explain.ExplainOptions, error) {
  2180  	es := explain.NewExplainDefaultOptions()
  2181  	if options == nil {
  2182  		return es, nil
  2183  	} else {
  2184  		for _, v := range options {
  2185  			if strings.EqualFold(v.Name, "VERBOSE") {
  2186  				if strings.EqualFold(v.Value, "TRUE") || v.Value == "NULL" {
  2187  					es.Verbose = true
  2188  				} else if strings.EqualFold(v.Value, "FALSE") {
  2189  					es.Verbose = false
  2190  				} else {
  2191  					return nil, moerr.NewInvalidInput(requestCtx, "invalid explain option '%s', valud '%s'", v.Name, v.Value)
  2192  				}
  2193  			} else if strings.EqualFold(v.Name, "ANALYZE") {
  2194  				if strings.EqualFold(v.Value, "TRUE") || v.Value == "NULL" {
  2195  					es.Analyze = true
  2196  				} else if strings.EqualFold(v.Value, "FALSE") {
  2197  					es.Analyze = false
  2198  				} else {
  2199  					return nil, moerr.NewInvalidInput(requestCtx, "invalid explain option '%s', valud '%s'", v.Name, v.Value)
  2200  				}
  2201  			} else if strings.EqualFold(v.Name, "FORMAT") {
  2202  				if strings.EqualFold(v.Value, "TEXT") {
  2203  					es.Format = explain.EXPLAIN_FORMAT_TEXT
  2204  				} else if strings.EqualFold(v.Value, "JSON") {
  2205  					return nil, moerr.NewNotSupported(requestCtx, "Unsupport explain format '%s'", v.Value)
  2206  				} else if strings.EqualFold(v.Value, "DOT") {
  2207  					return nil, moerr.NewNotSupported(requestCtx, "Unsupport explain format '%s'", v.Value)
  2208  				} else {
  2209  					return nil, moerr.NewInvalidInput(requestCtx, "invalid explain option '%s', valud '%s'", v.Name, v.Value)
  2210  				}
  2211  			} else {
  2212  				return nil, moerr.NewInvalidInput(requestCtx, "invalid explain option '%s', valud '%s'", v.Name, v.Value)
  2213  			}
  2214  		}
  2215  		return es, nil
  2216  	}
  2217  }
  2218  
  2219  func buildMoExplainQuery(explainColName string, buffer *explain.ExplainDataBuffer, session *Session, fill func(interface{}, *batch.Batch) error) error {
  2220  	bat := batch.New(true, []string{explainColName})
  2221  	rs := buffer.Lines
  2222  	vs := make([][]byte, len(rs))
  2223  
  2224  	count := 0
  2225  	for _, r := range rs {
  2226  		str := []byte(r)
  2227  		vs[count] = str
  2228  		count++
  2229  	}
  2230  	vs = vs[:count]
  2231  	vec := vector.NewWithBytes(types.T_varchar.ToType(), vs, nil, session.GetMemPool())
  2232  	bat.Vecs[0] = vec
  2233  	bat.InitZsOne(count)
  2234  
  2235  	err := fill(session, bat)
  2236  	vec.Free(session.GetMemPool())
  2237  	return err
  2238  }
  2239  
  2240  var _ ComputationWrapper = &TxnComputationWrapper{}
  2241  var _ ComputationWrapper = &NullComputationWrapper{}
  2242  
  2243  type TxnComputationWrapper struct {
  2244  	stmt    tree.Statement
  2245  	plan    *plan2.Plan
  2246  	proc    *process.Process
  2247  	ses     *Session
  2248  	compile *compile.Compile
  2249  
  2250  	uuid uuid.UUID
  2251  }
  2252  
  2253  func InitTxnComputationWrapper(ses *Session, stmt tree.Statement, proc *process.Process) *TxnComputationWrapper {
  2254  	uuid, _ := uuid.NewUUID()
  2255  	return &TxnComputationWrapper{
  2256  		stmt: stmt,
  2257  		proc: proc,
  2258  		ses:  ses,
  2259  		uuid: uuid,
  2260  	}
  2261  }
  2262  
  2263  func (cwft *TxnComputationWrapper) GetAst() tree.Statement {
  2264  	return cwft.stmt
  2265  }
  2266  
  2267  func (cwft *TxnComputationWrapper) GetProcess() *process.Process {
  2268  	return cwft.proc
  2269  }
  2270  
  2271  func (cwft *TxnComputationWrapper) SetDatabaseName(db string) error {
  2272  	return nil
  2273  }
  2274  
  2275  func (cwft *TxnComputationWrapper) GetColumns() ([]interface{}, error) {
  2276  	var err error
  2277  	cols := plan2.GetResultColumnsFromPlan(cwft.plan)
  2278  	switch cwft.GetAst().(type) {
  2279  	case *tree.ShowColumns:
  2280  		if len(cols) == 7 {
  2281  			cols = []*plan2.ColDef{
  2282  				{Typ: &plan2.Type{Id: int32(types.T_char)}, Name: "Field"},
  2283  				{Typ: &plan2.Type{Id: int32(types.T_char)}, Name: "Type"},
  2284  				{Typ: &plan2.Type{Id: int32(types.T_char)}, Name: "Null"},
  2285  				{Typ: &plan2.Type{Id: int32(types.T_char)}, Name: "Key"},
  2286  				{Typ: &plan2.Type{Id: int32(types.T_char)}, Name: "Default"},
  2287  				{Typ: &plan2.Type{Id: int32(types.T_char)}, Name: "Extra"},
  2288  				{Typ: &plan2.Type{Id: int32(types.T_char)}, Name: "Comment"},
  2289  			}
  2290  		} else {
  2291  			cols = []*plan2.ColDef{
  2292  				{Typ: &plan2.Type{Id: int32(types.T_char)}, Name: "Field"},
  2293  				{Typ: &plan2.Type{Id: int32(types.T_char)}, Name: "Type"},
  2294  				{Typ: &plan2.Type{Id: int32(types.T_char)}, Name: "Collation"},
  2295  				{Typ: &plan2.Type{Id: int32(types.T_char)}, Name: "Null"},
  2296  				{Typ: &plan2.Type{Id: int32(types.T_char)}, Name: "Key"},
  2297  				{Typ: &plan2.Type{Id: int32(types.T_char)}, Name: "Default"},
  2298  				{Typ: &plan2.Type{Id: int32(types.T_char)}, Name: "Extra"},
  2299  				{Typ: &plan2.Type{Id: int32(types.T_char)}, Name: "Privileges"},
  2300  				{Typ: &plan2.Type{Id: int32(types.T_char)}, Name: "Comment"},
  2301  			}
  2302  		}
  2303  	}
  2304  	columns := make([]interface{}, len(cols))
  2305  	for i, col := range cols {
  2306  		c := new(MysqlColumn)
  2307  		c.SetName(col.Name)
  2308  		c.SetOrgName(col.Name)
  2309  		c.SetTable(col.Typ.Table)
  2310  		c.SetOrgTable(col.Typ.Table)
  2311  		c.SetAutoIncr(col.Typ.AutoIncr)
  2312  		c.SetSchema(cwft.ses.GetTxnCompileCtx().DefaultDatabase())
  2313  		err = convertEngineTypeToMysqlType(cwft.ses.requestCtx, types.T(col.Typ.Id), c)
  2314  		if err != nil {
  2315  			return nil, err
  2316  		}
  2317  		setColFlag(c)
  2318  		setColLength(c, col.Typ.Width)
  2319  		setCharacter(c)
  2320  		c.SetDecimal(uint8(col.Typ.Scale))
  2321  		convertMysqlTextTypeToBlobType(c)
  2322  		columns[i] = c
  2323  	}
  2324  	return columns, err
  2325  }
  2326  
  2327  func (cwft *TxnComputationWrapper) GetClock() clock.Clock {
  2328  	rt := runtime.ProcessLevelRuntime()
  2329  	return rt.Clock()
  2330  }
  2331  
  2332  func (cwft *TxnComputationWrapper) GetAffectedRows() uint64 {
  2333  	return cwft.compile.GetAffectedRows()
  2334  }
  2335  
  2336  func (cwft *TxnComputationWrapper) Compile(requestCtx context.Context, u interface{}, fill func(interface{}, *batch.Batch) error) (interface{}, error) {
  2337  	var err error
  2338  	defer RecordStatementTxnID(requestCtx, cwft.ses)
  2339  	if cwft.ses.IfInitedTempEngine() {
  2340  		requestCtx = context.WithValue(requestCtx, defines.TemporaryDN{}, cwft.ses.GetTempTableStorage())
  2341  		cwft.ses.SetRequestContext(requestCtx)
  2342  		cwft.proc.Ctx = context.WithValue(cwft.proc.Ctx, defines.TemporaryDN{}, cwft.ses.GetTempTableStorage())
  2343  	}
  2344  	cacheHit := cwft.plan != nil
  2345  	if !cacheHit {
  2346  		cwft.plan, err = buildPlan(requestCtx, cwft.ses, cwft.ses.GetTxnCompileCtx(), cwft.stmt)
  2347  	} else if cwft.ses != nil && cwft.ses.GetTenantInfo() != nil {
  2348  		cwft.ses.accountId = getAccountId(requestCtx)
  2349  		err = authenticateCanExecuteStatementAndPlan(requestCtx, cwft.ses, cwft.stmt, cwft.plan)
  2350  	}
  2351  	if err != nil {
  2352  		return nil, err
  2353  	}
  2354  	cwft.ses.p = cwft.plan
  2355  	if ids := isResultQuery(cwft.plan); ids != nil {
  2356  		if err = checkPrivilege(ids, requestCtx, cwft.ses); err != nil {
  2357  			return nil, err
  2358  		}
  2359  	}
  2360  	if _, ok := cwft.stmt.(*tree.Execute); ok {
  2361  		executePlan := cwft.plan.GetDcl().GetExecute()
  2362  		stmtName := executePlan.GetName()
  2363  		prepareStmt, err := cwft.ses.GetPrepareStmt(stmtName)
  2364  		if err != nil {
  2365  			return nil, err
  2366  		}
  2367  
  2368  		// TODO check if schema change, obj.Obj is zero all the time in 0.6
  2369  		// for _, obj := range preparePlan.GetSchemas() {
  2370  		// 	newObj, _ := cwft.ses.txnCompileCtx.Resolve(obj.SchemaName, obj.ObjName)
  2371  		// 	if newObj == nil || newObj.Obj != obj.Obj {
  2372  		// 		return nil, moerr.NewInternalError("", fmt.Sprintf(ctx, "table '%s' has been changed, please reset Prepare statement '%s'", obj.ObjName, stmtName))
  2373  		// 	}
  2374  		// }
  2375  
  2376  		preparePlan := prepareStmt.PreparePlan.GetDcl().GetPrepare()
  2377  		if len(executePlan.Args) != len(preparePlan.ParamTypes) {
  2378  			return nil, moerr.NewInvalidInput(requestCtx, "Incorrect arguments to EXECUTE")
  2379  		}
  2380  		newPlan := plan2.DeepCopyPlan(preparePlan.Plan)
  2381  
  2382  		// replace ? and @var with their values
  2383  		resetParamRule := plan2.NewResetParamRefRule(requestCtx, executePlan.Args)
  2384  		resetVarRule := plan2.NewResetVarRefRule(cwft.ses.GetTxnCompileCtx(), cwft.ses.GetTxnCompileCtx().GetProcess())
  2385  		constantFoldRule := plan2.NewConstantFoldRule(cwft.ses.GetTxnCompileCtx())
  2386  		vp := plan2.NewVisitPlan(newPlan, []plan2.VisitPlanRule{resetParamRule, resetVarRule, constantFoldRule})
  2387  		err = vp.Visit(requestCtx)
  2388  		if err != nil {
  2389  			return nil, err
  2390  		}
  2391  
  2392  		// reset plan & stmt
  2393  		cwft.stmt = prepareStmt.PrepareStmt
  2394  		cwft.plan = newPlan
  2395  		// reset some special stmt for execute statement
  2396  		switch cwft.stmt.(type) {
  2397  		case *tree.ShowColumns:
  2398  			cwft.ses.SetShowStmtType(ShowColumns)
  2399  			cwft.ses.SetData(nil)
  2400  		case *tree.ShowTableStatus:
  2401  			cwft.ses.showStmtType = ShowTableStatus
  2402  			cwft.ses.SetData(nil)
  2403  		case *tree.SetVar, *tree.ShowVariables, *tree.ShowErrors, *tree.ShowWarnings:
  2404  			return nil, nil
  2405  		}
  2406  
  2407  		//check privilege
  2408  		err = authenticateUserCanExecutePrepareOrExecute(requestCtx, cwft.ses, prepareStmt.PrepareStmt, newPlan)
  2409  		if err != nil {
  2410  			return nil, err
  2411  		}
  2412  	} else {
  2413  		var vp *plan2.VisitPlan
  2414  		if cacheHit {
  2415  			vp = plan2.NewVisitPlan(cwft.plan, []plan2.VisitPlanRule{plan2.NewResetVarRefRule(cwft.ses.GetTxnCompileCtx(), cwft.ses.GetTxnCompileCtx().GetProcess()), plan2.NewRecomputeRealTimeRelatedFuncRule(cwft.ses.GetTxnCompileCtx().GetProcess())})
  2416  		} else {
  2417  			vp = plan2.NewVisitPlan(cwft.plan, []plan2.VisitPlanRule{plan2.NewResetVarRefRule(cwft.ses.GetTxnCompileCtx(), cwft.ses.GetTxnCompileCtx().GetProcess())})
  2418  		}
  2419  		err = vp.Visit(requestCtx)
  2420  		if err != nil {
  2421  			return nil, err
  2422  		}
  2423  	}
  2424  
  2425  	txnHandler := cwft.ses.GetTxnHandler()
  2426  	if cacheHit && cwft.plan.NeedImplicitTxn() {
  2427  		cwft.proc.TxnOperator, err = txnHandler.GetTxn()
  2428  		if err != nil {
  2429  			return nil, err
  2430  		}
  2431  	} else if cwft.plan.GetQuery().GetLoadTag() {
  2432  		cwft.proc.TxnOperator = txnHandler.GetTxnOnly()
  2433  	} else if cwft.plan.NeedImplicitTxn() {
  2434  		cwft.proc.TxnOperator, err = txnHandler.GetTxn()
  2435  		if err != nil {
  2436  			return nil, err
  2437  		}
  2438  	}
  2439  	addr := ""
  2440  	if len(cwft.ses.GetParameterUnit().ClusterNodes) > 0 {
  2441  		addr = cwft.ses.GetParameterUnit().ClusterNodes[0].Addr
  2442  	}
  2443  	cwft.proc.FileService = cwft.ses.GetParameterUnit().FileService
  2444  	cwft.compile = compile.New(addr, cwft.ses.GetDatabaseName(), cwft.ses.GetSql(), cwft.ses.GetUserName(), requestCtx, cwft.ses.GetStorage(), cwft.proc, cwft.stmt)
  2445  
  2446  	if _, ok := cwft.stmt.(*tree.ExplainAnalyze); ok {
  2447  		fill = func(obj interface{}, bat *batch.Batch) error { return nil }
  2448  	}
  2449  	err = cwft.compile.Compile(requestCtx, cwft.plan, cwft.ses, fill)
  2450  	if err != nil {
  2451  		return nil, err
  2452  	}
  2453  	// check if it is necessary to initialize the temporary engine
  2454  	if cwft.compile.NeedInitTempEngine(cwft.ses.IfInitedTempEngine()) {
  2455  		// 0. init memory-non-dist storage
  2456  		dnStore, err := cwft.ses.SetTempTableStorage(cwft.GetClock())
  2457  		if err != nil {
  2458  			return nil, err
  2459  		}
  2460  
  2461  		// temporary storage is passed through Ctx
  2462  		requestCtx = context.WithValue(requestCtx, defines.TemporaryDN{}, cwft.ses.GetTempTableStorage())
  2463  
  2464  		// 1. init memory-non-dist engine
  2465  		tempEngine := memoryengine.New(
  2466  			requestCtx,
  2467  			memoryengine.NewDefaultShardPolicy(
  2468  				mpool.MustNewZero(),
  2469  			),
  2470  			func() (logservicepb.ClusterDetails, error) {
  2471  				return logservicepb.ClusterDetails{
  2472  					DNStores: []logservicepb.DNStore{
  2473  						*dnStore,
  2474  					},
  2475  				}, nil
  2476  			},
  2477  			memoryengine.RandomIDGenerator,
  2478  		)
  2479  
  2480  		// 2. bind the temporary engine to the session and txnHandler
  2481  		cwft.ses.SetTempEngine(requestCtx, tempEngine)
  2482  		cwft.compile.SetTempEngine(requestCtx, tempEngine)
  2483  		txnHandler := cwft.ses.txnCompileCtx.txnHandler
  2484  		txnHandler.SetTempEngine(tempEngine)
  2485  
  2486  		// 3. init temp-db to store temporary relations
  2487  		err = tempEngine.Create(requestCtx, defines.TEMPORARY_DBNAME, cwft.ses.txnHandler.txn)
  2488  		if err != nil {
  2489  			return nil, err
  2490  		}
  2491  
  2492  		// 4. add auto_IncrementTable fortemp-db
  2493  		colexec.CreateAutoIncrTable(cwft.ses.GetStorage(), requestCtx, cwft.proc, defines.TEMPORARY_DBNAME)
  2494  
  2495  		cwft.ses.InitTempEngine = true
  2496  	}
  2497  	return cwft.compile, err
  2498  }
  2499  
  2500  func (cwft *TxnComputationWrapper) RecordExecPlan(ctx context.Context) error {
  2501  	if stm := motrace.StatementFromContext(ctx); stm != nil {
  2502  		stm.SetExecPlan(cwft.plan, SerializeExecPlan)
  2503  	}
  2504  	return nil
  2505  }
  2506  
  2507  func (cwft *TxnComputationWrapper) GetUUID() []byte {
  2508  	return cwft.uuid[:]
  2509  }
  2510  
  2511  func (cwft *TxnComputationWrapper) Run(ts uint64) error {
  2512  	logDebugf(cwft.ses.GetConciseProfile(), "compile.Run begin")
  2513  	defer func() {
  2514  		logDebugf(cwft.ses.GetConciseProfile(), "compile.Run end")
  2515  	}()
  2516  	err := cwft.compile.Run(ts)
  2517  	return err
  2518  }
  2519  
  2520  func (cwft *TxnComputationWrapper) GetLoadTag() bool {
  2521  	return cwft.plan.GetQuery().GetLoadTag()
  2522  }
  2523  
  2524  type NullComputationWrapper struct {
  2525  	*TxnComputationWrapper
  2526  }
  2527  
  2528  func InitNullComputationWrapper(ses *Session, stmt tree.Statement, proc *process.Process) *NullComputationWrapper {
  2529  	return &NullComputationWrapper{
  2530  		TxnComputationWrapper: InitTxnComputationWrapper(ses, stmt, proc),
  2531  	}
  2532  }
  2533  
  2534  func (ncw *NullComputationWrapper) GetAst() tree.Statement {
  2535  	return ncw.stmt
  2536  }
  2537  
  2538  func (ncw *NullComputationWrapper) SetDatabaseName(db string) error {
  2539  	return nil
  2540  }
  2541  
  2542  func (ncw *NullComputationWrapper) GetColumns() ([]interface{}, error) {
  2543  	return []interface{}{}, nil
  2544  }
  2545  
  2546  func (ncw *NullComputationWrapper) GetAffectedRows() uint64 {
  2547  	return 0
  2548  }
  2549  
  2550  func (ncw *NullComputationWrapper) Compile(requestCtx context.Context, u interface{}, fill func(interface{}, *batch.Batch) error) (interface{}, error) {
  2551  	return nil, nil
  2552  }
  2553  
  2554  func (ncw *NullComputationWrapper) RecordExecPlan(ctx context.Context) error {
  2555  	return nil
  2556  }
  2557  
  2558  func (ncw *NullComputationWrapper) GetUUID() []byte {
  2559  	return ncw.uuid[:]
  2560  }
  2561  
  2562  func (ncw *NullComputationWrapper) Run(ts uint64) error {
  2563  	return nil
  2564  }
  2565  
  2566  func (ncw *NullComputationWrapper) GetLoadTag() bool {
  2567  	return false
  2568  }
  2569  
  2570  func buildPlan(requestCtx context.Context, ses *Session, ctx plan2.CompilerContext, stmt tree.Statement) (*plan2.Plan, error) {
  2571  	var ret *plan2.Plan
  2572  	var err error
  2573  	if ses != nil {
  2574  		ses.accountId = getAccountId(requestCtx)
  2575  	}
  2576  	if s, ok := stmt.(*tree.Insert); ok {
  2577  		if _, ok := s.Rows.Select.(*tree.ValuesClause); ok {
  2578  			ret, err = plan2.BuildPlan(ctx, stmt)
  2579  			if err != nil {
  2580  				return nil, err
  2581  			}
  2582  		}
  2583  	}
  2584  	if ret != nil {
  2585  		if ses != nil && ses.GetTenantInfo() != nil {
  2586  			err = authenticateCanExecuteStatementAndPlan(requestCtx, ses, stmt, ret)
  2587  			if err != nil {
  2588  				return nil, err
  2589  			}
  2590  		}
  2591  		return ret, err
  2592  	}
  2593  	switch stmt := stmt.(type) {
  2594  	case *tree.Select, *tree.ParenSelect, *tree.ValuesStatement,
  2595  		*tree.Update, *tree.Delete, *tree.Insert,
  2596  		*tree.ShowDatabases, *tree.ShowTables, *tree.ShowColumns, *tree.ShowColumnNumber, *tree.ShowTableNumber,
  2597  		*tree.ShowCreateDatabase, *tree.ShowCreateTable, *tree.ShowIndex,
  2598  		*tree.ExplainStmt, *tree.ExplainAnalyze:
  2599  		opt := plan2.NewBaseOptimizer(ctx)
  2600  		optimized, err := opt.Optimize(stmt)
  2601  		if err != nil {
  2602  			return nil, err
  2603  		}
  2604  		ret = &plan2.Plan{
  2605  			Plan: &plan2.Plan_Query{
  2606  				Query: optimized,
  2607  			},
  2608  		}
  2609  	default:
  2610  		ret, err = plan2.BuildPlan(ctx, stmt)
  2611  	}
  2612  	if ret != nil {
  2613  		if ses != nil && ses.GetTenantInfo() != nil {
  2614  			err = authenticateCanExecuteStatementAndPlan(requestCtx, ses, stmt, ret)
  2615  			if err != nil {
  2616  				return nil, err
  2617  			}
  2618  		}
  2619  	}
  2620  	return ret, err
  2621  }
  2622  
  2623  /*
  2624  GetComputationWrapper gets the execs from the computation engine
  2625  */
  2626  var GetComputationWrapper = func(db, sql, user string, eng engine.Engine, proc *process.Process, ses *Session) ([]ComputationWrapper, error) {
  2627  	var cw []ComputationWrapper = nil
  2628  	if cached := ses.getCachedPlan(sql); cached != nil {
  2629  		for i, stmt := range cached.stmts {
  2630  			tcw := InitTxnComputationWrapper(ses, stmt, proc)
  2631  			tcw.plan = cached.plans[i]
  2632  			cw = append(cw, tcw)
  2633  		}
  2634  		return cw, nil
  2635  	}
  2636  
  2637  	var stmts []tree.Statement = nil
  2638  	var cmdFieldStmt *InternalCmdFieldList
  2639  	var err error
  2640  	if isCmdFieldListSql(sql) {
  2641  		cmdFieldStmt, err = parseCmdFieldList(proc.Ctx, sql)
  2642  		if err != nil {
  2643  			return nil, err
  2644  		}
  2645  		stmts = append(stmts, cmdFieldStmt)
  2646  	} else {
  2647  		stmts, err = parsers.Parse(proc.Ctx, dialect.MYSQL, sql)
  2648  		if err != nil {
  2649  			return nil, err
  2650  		}
  2651  	}
  2652  
  2653  	for _, stmt := range stmts {
  2654  		cw = append(cw, InitTxnComputationWrapper(ses, stmt, proc))
  2655  	}
  2656  	return cw, nil
  2657  }
  2658  
  2659  func getStmtExecutor(ses *Session, proc *process.Process, base *baseStmtExecutor, stmt tree.Statement) (StmtExecutor, error) {
  2660  	var err error
  2661  	var ret StmtExecutor
  2662  	switch st := stmt.(type) {
  2663  	//PART 1: the statements with the result set
  2664  	case *tree.Select:
  2665  		ret = (&SelectExecutor{
  2666  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2667  				base,
  2668  			},
  2669  			sel: st,
  2670  		})
  2671  	case *tree.ValuesStatement:
  2672  		ret = (&ValuesStmtExecutor{
  2673  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2674  				base,
  2675  			},
  2676  			sel: st,
  2677  		})
  2678  	case *tree.ShowCreateTable:
  2679  		ret = (&ShowCreateTableExecutor{
  2680  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2681  				base,
  2682  			},
  2683  			sct: st,
  2684  		})
  2685  	case *tree.ShowCreateDatabase:
  2686  		ret = (&ShowCreateDatabaseExecutor{
  2687  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2688  				base,
  2689  			},
  2690  			scd: st,
  2691  		})
  2692  	case *tree.ShowTables:
  2693  		ret = (&ShowTablesExecutor{
  2694  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2695  				base,
  2696  			},
  2697  			st: st,
  2698  		})
  2699  	case *tree.ShowDatabases:
  2700  		ret = (&ShowDatabasesExecutor{
  2701  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2702  				base,
  2703  			},
  2704  			sd: st,
  2705  		})
  2706  	case *tree.ShowColumns:
  2707  		ret = (&ShowColumnsExecutor{
  2708  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2709  				base,
  2710  			},
  2711  			sc: st,
  2712  		})
  2713  	case *tree.ShowProcessList:
  2714  		ret = (&ShowProcessListExecutor{
  2715  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2716  				base,
  2717  			},
  2718  			spl: st,
  2719  		})
  2720  	case *tree.ShowStatus:
  2721  		ret = (&ShowStatusExecutor{
  2722  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2723  				base,
  2724  			},
  2725  			ss: st,
  2726  		})
  2727  	case *tree.ShowTableStatus:
  2728  		ret = (&ShowTableStatusExecutor{
  2729  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2730  				base,
  2731  			},
  2732  			sts: st,
  2733  		})
  2734  	case *tree.ShowGrants:
  2735  		ret = (&ShowGrantsExecutor{
  2736  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2737  				base,
  2738  			},
  2739  			sg: st,
  2740  		})
  2741  	case *tree.ShowIndex:
  2742  		ret = (&ShowIndexExecutor{
  2743  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2744  				base,
  2745  			},
  2746  			si: st,
  2747  		})
  2748  	case *tree.ShowCreateView:
  2749  		ret = (&ShowCreateViewExecutor{
  2750  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2751  				base,
  2752  			},
  2753  			scv: st,
  2754  		})
  2755  	case *tree.ShowTarget:
  2756  		ret = (&ShowTargetExecutor{
  2757  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2758  				base,
  2759  			},
  2760  			st: st,
  2761  		})
  2762  	case *tree.ExplainFor:
  2763  		ret = (&ExplainForExecutor{
  2764  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2765  				base,
  2766  			},
  2767  			ef: st,
  2768  		})
  2769  	case *tree.ExplainStmt:
  2770  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2771  		ret = (&ExplainStmtExecutor{
  2772  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2773  				base,
  2774  			},
  2775  			es: st,
  2776  		})
  2777  	case *tree.ShowVariables:
  2778  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2779  		ret = (&ShowVariablesExecutor{
  2780  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2781  				base,
  2782  			},
  2783  			sv: st,
  2784  		})
  2785  	case *tree.ShowErrors:
  2786  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2787  		ret = (&ShowErrorsExecutor{
  2788  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2789  				base,
  2790  			},
  2791  			se: st,
  2792  		})
  2793  	case *tree.ShowWarnings:
  2794  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2795  		ret = (&ShowWarningsExecutor{
  2796  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2797  				base,
  2798  			},
  2799  			sw: st,
  2800  		})
  2801  	case *tree.AnalyzeStmt:
  2802  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2803  		ret = (&AnalyzeStmtExecutor{
  2804  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2805  				base,
  2806  			},
  2807  			as: st,
  2808  		})
  2809  	case *tree.ExplainAnalyze:
  2810  		ret = (&ExplainAnalyzeExecutor{
  2811  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2812  				base,
  2813  			},
  2814  			ea: st,
  2815  		})
  2816  	case *InternalCmdFieldList:
  2817  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2818  		ret = (&InternalCmdFieldListExecutor{
  2819  			resultSetStmtExecutor: &resultSetStmtExecutor{
  2820  				base,
  2821  			},
  2822  			icfl: st,
  2823  		})
  2824  	//PART 2: the statement with the status only
  2825  	case *tree.BeginTransaction:
  2826  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2827  		ret = (&BeginTxnExecutor{
  2828  			statusStmtExecutor: &statusStmtExecutor{
  2829  				base,
  2830  			},
  2831  			bt: st,
  2832  		})
  2833  	case *tree.CommitTransaction:
  2834  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2835  		ret = (&CommitTxnExecutor{
  2836  			statusStmtExecutor: &statusStmtExecutor{
  2837  				base,
  2838  			},
  2839  			ct: st,
  2840  		})
  2841  	case *tree.RollbackTransaction:
  2842  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2843  		ret = (&RollbackTxnExecutor{
  2844  			statusStmtExecutor: &statusStmtExecutor{
  2845  				base,
  2846  			},
  2847  			rt: st,
  2848  		})
  2849  	case *tree.SetRole:
  2850  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2851  		ret = (&SetRoleExecutor{
  2852  			statusStmtExecutor: &statusStmtExecutor{
  2853  				base,
  2854  			},
  2855  			sr: st,
  2856  		})
  2857  	case *tree.Use:
  2858  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2859  		ret = (&UseExecutor{
  2860  			statusStmtExecutor: &statusStmtExecutor{
  2861  				base,
  2862  			},
  2863  			u: st,
  2864  		})
  2865  	case *tree.MoDump:
  2866  		//TODO:
  2867  		err = moerr.NewInternalError(proc.Ctx, "needs to add modump")
  2868  	case *tree.DropDatabase:
  2869  		ret = (&DropDatabaseExecutor{
  2870  			statusStmtExecutor: &statusStmtExecutor{
  2871  				base,
  2872  			},
  2873  			dd: st,
  2874  		})
  2875  	case *tree.Import:
  2876  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2877  		ret = (&ImportExecutor{
  2878  			statusStmtExecutor: &statusStmtExecutor{
  2879  				base,
  2880  			},
  2881  			i: st,
  2882  		})
  2883  	case *tree.PrepareStmt:
  2884  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2885  		ret = (&PrepareStmtExecutor{
  2886  			statusStmtExecutor: &statusStmtExecutor{
  2887  				base,
  2888  			},
  2889  			ps: st,
  2890  		})
  2891  	case *tree.PrepareString:
  2892  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2893  		ret = (&PrepareStringExecutor{
  2894  			statusStmtExecutor: &statusStmtExecutor{
  2895  				base,
  2896  			},
  2897  			ps: st,
  2898  		})
  2899  	case *tree.Deallocate:
  2900  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2901  		ret = (&DeallocateExecutor{
  2902  			statusStmtExecutor: &statusStmtExecutor{
  2903  				base,
  2904  			},
  2905  			d: st,
  2906  		})
  2907  	case *tree.SetVar:
  2908  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2909  		ret = (&SetVarExecutor{
  2910  			statusStmtExecutor: &statusStmtExecutor{
  2911  				base,
  2912  			},
  2913  			sv: st,
  2914  		})
  2915  	case *tree.Delete:
  2916  		ret = (&DeleteExecutor{
  2917  			statusStmtExecutor: &statusStmtExecutor{
  2918  				base,
  2919  			},
  2920  			d: st,
  2921  		})
  2922  	case *tree.Update:
  2923  		ret = (&UpdateExecutor{
  2924  			statusStmtExecutor: &statusStmtExecutor{
  2925  				base,
  2926  			},
  2927  			u: st,
  2928  		})
  2929  	case *tree.CreateAccount:
  2930  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2931  		ret = (&CreateAccountExecutor{
  2932  			statusStmtExecutor: &statusStmtExecutor{
  2933  				base,
  2934  			},
  2935  			ca: st,
  2936  		})
  2937  	case *tree.DropAccount:
  2938  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2939  		ret = (&DropAccountExecutor{
  2940  			statusStmtExecutor: &statusStmtExecutor{
  2941  				base,
  2942  			},
  2943  			da: st,
  2944  		})
  2945  	case *tree.AlterAccount:
  2946  		ret = (&AlterAccountExecutor{
  2947  			statusStmtExecutor: &statusStmtExecutor{
  2948  				base,
  2949  			},
  2950  			aa: st,
  2951  		})
  2952  	case *tree.CreateUser:
  2953  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2954  		ret = (&CreateUserExecutor{
  2955  			statusStmtExecutor: &statusStmtExecutor{
  2956  				base,
  2957  			},
  2958  			cu: st,
  2959  		})
  2960  	case *tree.DropUser:
  2961  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2962  		ret = (&DropUserExecutor{
  2963  			statusStmtExecutor: &statusStmtExecutor{
  2964  				base,
  2965  			},
  2966  			du: st,
  2967  		})
  2968  	case *tree.AlterUser:
  2969  		ret = (&AlterUserExecutor{
  2970  			statusStmtExecutor: &statusStmtExecutor{
  2971  				base,
  2972  			},
  2973  			au: st,
  2974  		})
  2975  	case *tree.CreateRole:
  2976  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2977  		ret = (&CreateRoleExecutor{
  2978  			statusStmtExecutor: &statusStmtExecutor{
  2979  				base,
  2980  			},
  2981  			cr: st,
  2982  		})
  2983  	case *tree.DropRole:
  2984  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2985  		ret = (&DropRoleExecutor{
  2986  			statusStmtExecutor: &statusStmtExecutor{
  2987  				base,
  2988  			},
  2989  			dr: st,
  2990  		})
  2991  	case *tree.Grant:
  2992  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  2993  		ret = (&GrantExecutor{
  2994  			statusStmtExecutor: &statusStmtExecutor{
  2995  				base,
  2996  			},
  2997  			g: st,
  2998  		})
  2999  	case *tree.Revoke:
  3000  		base.ComputationWrapper = InitNullComputationWrapper(ses, st, proc)
  3001  		ret = (&RevokeExecutor{
  3002  			statusStmtExecutor: &statusStmtExecutor{
  3003  				base,
  3004  			},
  3005  			r: st,
  3006  		})
  3007  	case *tree.CreateTable:
  3008  		ret = (&CreateTableExecutor{
  3009  			statusStmtExecutor: &statusStmtExecutor{
  3010  				base,
  3011  			},
  3012  			ct: st,
  3013  		})
  3014  	case *tree.DropTable:
  3015  		ret = (&DropTableExecutor{
  3016  			statusStmtExecutor: &statusStmtExecutor{
  3017  				base,
  3018  			},
  3019  			dt: st,
  3020  		})
  3021  	case *tree.CreateDatabase:
  3022  		ret = (&CreateDatabaseExecutor{
  3023  			statusStmtExecutor: &statusStmtExecutor{
  3024  				base,
  3025  			},
  3026  			cd: st,
  3027  		})
  3028  	case *tree.CreateIndex:
  3029  		ret = (&CreateIndexExecutor{
  3030  			statusStmtExecutor: &statusStmtExecutor{
  3031  				base,
  3032  			},
  3033  			ci: st,
  3034  		})
  3035  	case *tree.DropIndex:
  3036  		ret = (&DropIndexExecutor{
  3037  			statusStmtExecutor: &statusStmtExecutor{
  3038  				base,
  3039  			},
  3040  			di: st,
  3041  		})
  3042  	case *tree.CreateView:
  3043  		ret = (&CreateViewExecutor{
  3044  			statusStmtExecutor: &statusStmtExecutor{
  3045  				base,
  3046  			},
  3047  			cv: st,
  3048  		})
  3049  	case *tree.AlterView:
  3050  		ret = (&AlterViewExecutor{
  3051  			statusStmtExecutor: &statusStmtExecutor{
  3052  				base,
  3053  			},
  3054  			av: st,
  3055  		})
  3056  	case *tree.DropView:
  3057  		ret = (&DropViewExecutor{
  3058  			statusStmtExecutor: &statusStmtExecutor{
  3059  				base,
  3060  			},
  3061  			dv: st,
  3062  		})
  3063  	case *tree.Insert:
  3064  		ret = (&InsertExecutor{
  3065  			statusStmtExecutor: &statusStmtExecutor{
  3066  				base,
  3067  			},
  3068  			i: st,
  3069  		})
  3070  	case *tree.Load:
  3071  		ret = (&LoadExecutor{
  3072  			statusStmtExecutor: &statusStmtExecutor{
  3073  				base,
  3074  			},
  3075  			l: st,
  3076  		})
  3077  	case *tree.SetDefaultRole:
  3078  		ret = (&SetDefaultRoleExecutor{
  3079  			statusStmtExecutor: &statusStmtExecutor{
  3080  				base,
  3081  			},
  3082  			sdr: st,
  3083  		})
  3084  	case *tree.SetPassword:
  3085  		ret = (&SetPasswordExecutor{
  3086  			statusStmtExecutor: &statusStmtExecutor{
  3087  				base,
  3088  			},
  3089  			sp: st,
  3090  		})
  3091  	case *tree.TruncateTable:
  3092  		ret = (&TruncateTableExecutor{
  3093  			statusStmtExecutor: &statusStmtExecutor{
  3094  				base,
  3095  			},
  3096  			tt: st,
  3097  		})
  3098  	//PART 3: hybrid
  3099  	case *tree.Execute:
  3100  		ret = &ExecuteExecutor{
  3101  			baseStmtExecutor: base,
  3102  			e:                st,
  3103  		}
  3104  	default:
  3105  		return nil, moerr.NewInternalError(proc.Ctx, "no such statement %s", stmt.String())
  3106  	}
  3107  	return ret, err
  3108  }
  3109  
  3110  var GetStmtExecList = func(db, sql, user string, eng engine.Engine, proc *process.Process, ses *Session) ([]StmtExecutor, error) {
  3111  	var stmtExecList []StmtExecutor = nil
  3112  	var stmtExec StmtExecutor
  3113  	var stmts []tree.Statement = nil
  3114  	var cmdFieldStmt *InternalCmdFieldList
  3115  	var err error
  3116  
  3117  	appendStmtExec := func(se StmtExecutor) {
  3118  		stmtExecList = append(stmtExecList, se)
  3119  	}
  3120  
  3121  	if isCmdFieldListSql(sql) {
  3122  		cmdFieldStmt, err = parseCmdFieldList(proc.Ctx, sql)
  3123  		if err != nil {
  3124  			return nil, err
  3125  		}
  3126  		stmts = append(stmts, cmdFieldStmt)
  3127  	} else {
  3128  		stmts, err = parsers.Parse(proc.Ctx, dialect.MYSQL, sql)
  3129  		if err != nil {
  3130  			return nil, err
  3131  		}
  3132  	}
  3133  
  3134  	for _, stmt := range stmts {
  3135  		cw := InitTxnComputationWrapper(ses, stmt, proc)
  3136  		base := &baseStmtExecutor{}
  3137  		base.ComputationWrapper = cw
  3138  		stmtExec, err = getStmtExecutor(ses, proc, base, stmt)
  3139  		if err != nil {
  3140  			return nil, err
  3141  		}
  3142  		appendStmtExec(stmtExec)
  3143  	}
  3144  	return stmtExecList, nil
  3145  }
  3146  
  3147  func incStatementCounter(tenant string, stmt tree.Statement) {
  3148  	metric.StatementCounter(tenant, getStatementType(stmt).GetQueryType()).Inc()
  3149  }
  3150  
  3151  func incTransactionCounter(tenant string) {
  3152  	metric.TransactionCounter(tenant).Inc()
  3153  }
  3154  
  3155  func incTransactionErrorsCounter(tenant string, t metric.SQLType) {
  3156  	if t == metric.SQLTypeRollback {
  3157  		return
  3158  	}
  3159  	metric.TransactionErrorsCounter(tenant, t).Inc()
  3160  }
  3161  
  3162  func incStatementErrorsCounter(tenant string, stmt tree.Statement) {
  3163  	metric.StatementErrorsCounter(tenant, getStatementType(stmt).GetQueryType()).Inc()
  3164  }
  3165  
  3166  type unknownStatementType struct {
  3167  	tree.StatementType
  3168  }
  3169  
  3170  func (unknownStatementType) GetStatementType() string { return "Unknown" }
  3171  func (unknownStatementType) GetQueryType() string     { return tree.QueryTypeOth }
  3172  
  3173  func getStatementType(stmt tree.Statement) tree.StatementType {
  3174  	switch stmt.(type) {
  3175  	case tree.StatementType:
  3176  		return stmt
  3177  	default:
  3178  		return unknownStatementType{}
  3179  	}
  3180  }
  3181  
  3182  // authenticateUserCanExecuteStatement checks the user can execute the statement
  3183  func authenticateUserCanExecuteStatement(requestCtx context.Context, ses *Session, stmt tree.Statement) error {
  3184  	requestCtx, span := trace.Debug(requestCtx, "authenticateUserCanExecuteStatement")
  3185  	defer span.End()
  3186  	if ses.skipCheckPrivilege() {
  3187  		return nil
  3188  	}
  3189  	if ses.skipAuthForSpecialUser() {
  3190  		return nil
  3191  	}
  3192  	var havePrivilege bool
  3193  	var err error
  3194  	if ses.GetTenantInfo() != nil {
  3195  		ses.SetPrivilege(determinePrivilegeSetOfStatement(stmt))
  3196  		havePrivilege, err = authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(requestCtx, ses, stmt)
  3197  		if err != nil {
  3198  			return err
  3199  		}
  3200  
  3201  		if !havePrivilege {
  3202  			err = moerr.NewInternalError(requestCtx, "do not have privilege to execute the statement")
  3203  			return err
  3204  		}
  3205  
  3206  		havePrivilege, err = authenticateUserCanExecuteStatementWithObjectTypeNone(requestCtx, ses, stmt)
  3207  		if err != nil {
  3208  			return err
  3209  		}
  3210  
  3211  		if !havePrivilege {
  3212  			err = moerr.NewInternalError(requestCtx, "do not have privilege to execute the statement")
  3213  			return err
  3214  		}
  3215  	}
  3216  	return err
  3217  }
  3218  
  3219  // authenticateCanExecuteStatementAndPlan checks the user can execute the statement and its plan
  3220  func authenticateCanExecuteStatementAndPlan(requestCtx context.Context, ses *Session, stmt tree.Statement, p *plan.Plan) error {
  3221  	if ses.skipCheckPrivilege() {
  3222  		return nil
  3223  	}
  3224  	if ses.skipAuthForSpecialUser() {
  3225  		return nil
  3226  	}
  3227  	yes, err := authenticateUserCanExecuteStatementWithObjectTypeDatabaseAndTable(requestCtx, ses, stmt, p)
  3228  	if err != nil {
  3229  		return err
  3230  	}
  3231  	if !yes {
  3232  		return moerr.NewInternalError(requestCtx, "do not have privilege to execute the statement")
  3233  	}
  3234  	return nil
  3235  }
  3236  
  3237  // authenticatePrivilegeOfPrepareAndExecute checks the user can execute the Prepare or Execute statement
  3238  func authenticateUserCanExecutePrepareOrExecute(requestCtx context.Context, ses *Session, stmt tree.Statement, p *plan.Plan) error {
  3239  	err := authenticateUserCanExecuteStatement(requestCtx, ses, stmt)
  3240  	if err != nil {
  3241  		return err
  3242  	}
  3243  	err = authenticateCanExecuteStatementAndPlan(requestCtx, ses, stmt, p)
  3244  	if err != nil {
  3245  		return err
  3246  	}
  3247  	return err
  3248  }
  3249  
  3250  // canExecuteStatementInUncommittedTxn checks the user can execute the statement in an uncommitted transaction
  3251  func (mce *MysqlCmdExecutor) canExecuteStatementInUncommittedTransaction(requestCtx context.Context, stmt tree.Statement) error {
  3252  	can, err := StatementCanBeExecutedInUncommittedTransaction(mce.GetSession(), stmt)
  3253  	if err != nil {
  3254  		return err
  3255  	}
  3256  	if !can {
  3257  		//is ddl statement
  3258  		if IsDDL(stmt) {
  3259  			return moerr.NewInternalError(requestCtx, onlyCreateStatementErrorInfo())
  3260  		} else if IsAdministrativeStatement(stmt) {
  3261  			return moerr.NewInternalError(requestCtx, administrativeCommandIsUnsupportedInTxnErrorInfo())
  3262  		} else if IsParameterModificationStatement(stmt) {
  3263  			return moerr.NewInternalError(requestCtx, parameterModificationInTxnErrorInfo())
  3264  		} else {
  3265  			return moerr.NewInternalError(requestCtx, unclassifiedStatementInUncommittedTxnErrorInfo())
  3266  		}
  3267  	}
  3268  	return nil
  3269  }
  3270  
  3271  func (ses *Session) getSqlType(sql string) {
  3272  	tenant := ses.GetTenantInfo()
  3273  	if tenant == nil || strings.HasPrefix(sql, cmdFieldListSql) {
  3274  		ses.sqlSourceType = intereSql
  3275  		return
  3276  	}
  3277  	flag, _, _ := isSpecialUser(tenant.User)
  3278  	if flag {
  3279  		ses.sqlSourceType = intereSql
  3280  		return
  3281  	}
  3282  	p1 := strings.Index(sql, "/*")
  3283  	p2 := strings.Index(sql, "*/")
  3284  	if p1 < 0 || p2 < 0 || p2 <= p1+1 {
  3285  		ses.sqlSourceType = externSql
  3286  		return
  3287  	}
  3288  	source := strings.TrimSpace(sql[p1+2 : p2])
  3289  	if source == cloudUserTag {
  3290  		ses.sqlSourceType = cloudUserSql
  3291  	} else if source == cloudNoUserTag {
  3292  		ses.sqlSourceType = cloudNoUserSql
  3293  	} else {
  3294  		ses.sqlSourceType = externSql
  3295  	}
  3296  }
  3297  
  3298  func (mce *MysqlCmdExecutor) processLoadLocal(ctx context.Context, param *tree.ExternParam, writer *io.PipeWriter) (err error) {
  3299  	ses := mce.GetSession()
  3300  	proto := ses.GetMysqlProtocol()
  3301  	defer func() {
  3302  		err2 := writer.Close()
  3303  		if err == nil {
  3304  			err = err2
  3305  		}
  3306  	}()
  3307  	err = plan2.InitInfileParam(param)
  3308  	if err != nil {
  3309  		return
  3310  	}
  3311  	err = proto.sendLocalInfileRequest(param.Filepath)
  3312  	if err != nil {
  3313  		return
  3314  	}
  3315  	start := time.Now()
  3316  	var msg interface{}
  3317  	msg, err = proto.GetTcpConnection().Read(goetty.ReadOptions{})
  3318  	if err != nil {
  3319  		if moerr.IsMoErrCode(err, moerr.ErrInvalidInput) {
  3320  			err = moerr.NewFileNotFound(ctx, param.Filepath)
  3321  		}
  3322  		proto.SetSequenceID(proto.GetSequenceId() + 1)
  3323  		return
  3324  	}
  3325  
  3326  	packet, ok := msg.(*Packet)
  3327  	if !ok {
  3328  		proto.SetSequenceID(proto.GetSequenceId() + 1)
  3329  		err = moerr.NewInvalidInput(ctx, "invalid packet")
  3330  		return
  3331  	}
  3332  
  3333  	proto.SetSequenceID(uint8(packet.SequenceID + 1))
  3334  	seq := uint8(packet.SequenceID + 1)
  3335  	length := packet.Length
  3336  	if length == 0 {
  3337  		return
  3338  	}
  3339  
  3340  	skipWrite := false
  3341  	// If inner error occurs(unexpected or expected(ctrl-c)), proc.LoadLocalReader will be closed.
  3342  	// Then write will return error, but we need to read the rest of the data and not write it to pipe.
  3343  	// So we need a flag[skipWrite] to tell us whether we need to write the data to pipe.
  3344  	// https://github.com/matrixorigin/matrixone/issues/6665#issuecomment-1422236478
  3345  
  3346  	_, err = writer.Write(packet.Payload)
  3347  	if err != nil {
  3348  		skipWrite = true // next, we just need read the rest of the data,no need to write it to pipe.
  3349  		logErrorf(ses.GetConciseProfile(), "load local '%s', write error: %v", param.Filepath, err)
  3350  	}
  3351  	epoch, printEvery, minReadTime, maxReadTime, minWriteTime, maxWriteTime := uint64(0), uint64(1024), 24*time.Hour, time.Nanosecond, 24*time.Hour, time.Nanosecond
  3352  	for {
  3353  		readStart := time.Now()
  3354  		msg, err = proto.GetTcpConnection().Read(goetty.ReadOptions{})
  3355  		if err != nil {
  3356  			if moerr.IsMoErrCode(err, moerr.ErrInvalidInput) {
  3357  				seq += 1
  3358  				proto.SetSequenceID(seq)
  3359  				err = nil
  3360  			}
  3361  			break
  3362  		}
  3363  		readTime := time.Since(readStart)
  3364  		if readTime > maxReadTime {
  3365  			maxReadTime = readTime
  3366  		}
  3367  		if readTime < minReadTime {
  3368  			minReadTime = readTime
  3369  		}
  3370  		packet, ok = msg.(*Packet)
  3371  		if !ok {
  3372  			err = moerr.NewInvalidInput(ctx, "invalid packet")
  3373  			seq += 1
  3374  			proto.SetSequenceID(seq)
  3375  			break
  3376  		}
  3377  		seq = uint8(packet.SequenceID + 1)
  3378  		proto.SetSequenceID(seq)
  3379  
  3380  		writeStart := time.Now()
  3381  		if !skipWrite {
  3382  			_, err = writer.Write(packet.Payload)
  3383  			if err != nil {
  3384  				logErrorf(ses.GetConciseProfile(), "load local '%s', epoch: %d, write error: %v", param.Filepath, epoch, err)
  3385  				skipWrite = true
  3386  			}
  3387  			writeTime := time.Since(writeStart)
  3388  			if writeTime > maxWriteTime {
  3389  				maxWriteTime = writeTime
  3390  			}
  3391  			if writeTime < minWriteTime {
  3392  				minWriteTime = writeTime
  3393  			}
  3394  		}
  3395  		if epoch%printEvery == 0 {
  3396  			logInfof(ses.GetConciseProfile(), "load local '%s', epoch: %d, skipWrite: %v, minReadTime: %s, maxReadTime: %s, minWriteTime: %s, maxWriteTime: %s,", param.Filepath, epoch, skipWrite, minReadTime.String(), maxReadTime.String(), minWriteTime.String(), maxWriteTime.String())
  3397  			minReadTime, maxReadTime, minWriteTime, maxWriteTime = 24*time.Hour, time.Nanosecond, 24*time.Hour, time.Nanosecond
  3398  		}
  3399  		epoch += 1
  3400  	}
  3401  	logInfof(ses.GetConciseProfile(), "load local '%s', read&write all data from client cost: %s", param.Filepath, time.Since(start))
  3402  	return
  3403  }
  3404  
  3405  // execute query
  3406  func (mce *MysqlCmdExecutor) doComQuery(requestCtx context.Context, sql string) (retErr error) {
  3407  	beginInstant := time.Now()
  3408  	ses := mce.GetSession()
  3409  	ses.getSqlType(sql)
  3410  	ses.SetShowStmtType(NotShowStatement)
  3411  	proto := ses.GetMysqlProtocol()
  3412  	ses.SetSql(sql)
  3413  	ses.GetExportParam().Outfile = false
  3414  	pu := ses.GetParameterUnit()
  3415  	proc := process.New(
  3416  		requestCtx,
  3417  		ses.GetMemPool(),
  3418  		ses.GetTxnHandler().GetTxnClient(),
  3419  		ses.GetTxnHandler().GetTxnOperator(),
  3420  		pu.FileService,
  3421  		pu.GetClusterDetails,
  3422  	)
  3423  	proc.Id = mce.getNextProcessId()
  3424  	proc.Lim.Size = pu.SV.ProcessLimitationSize
  3425  	proc.Lim.BatchRows = pu.SV.ProcessLimitationBatchRows
  3426  	proc.Lim.MaxMsgSize = pu.SV.MaxMessageSize
  3427  	proc.Lim.PartitionRows = pu.SV.ProcessLimitationPartitionRows
  3428  	proc.SessionInfo = process.SessionInfo{
  3429  		User:              ses.GetUserName(),
  3430  		Host:              pu.SV.Host,
  3431  		ConnectionID:      uint64(proto.ConnectionID()),
  3432  		Database:          ses.GetDatabaseName(),
  3433  		Version:           pu.SV.ServerVersionPrefix + serverVersion.Load().(string),
  3434  		TimeZone:          ses.GetTimeZone(),
  3435  		StorageEngine:     pu.StorageEngine,
  3436  		LastInsertID:      ses.GetLastInsertID(),
  3437  		AutoIncrCaches:    ses.GetAutoIncrCaches(),
  3438  		AutoIncrCacheSize: ses.pu.SV.AutoIncrCacheSize,
  3439  	}
  3440  	if ses.GetTenantInfo() != nil {
  3441  		proc.SessionInfo.Account = ses.GetTenantInfo().GetTenant()
  3442  		proc.SessionInfo.AccountId = ses.GetTenantInfo().GetTenantID()
  3443  		proc.SessionInfo.Role = ses.GetTenantInfo().GetDefaultRole()
  3444  		proc.SessionInfo.RoleId = ses.GetTenantInfo().GetDefaultRoleID()
  3445  		proc.SessionInfo.UserId = ses.GetTenantInfo().GetUserID()
  3446  
  3447  		if len(ses.GetTenantInfo().GetVersion()) != 0 {
  3448  			proc.SessionInfo.Version = ses.GetTenantInfo().GetVersion()
  3449  		}
  3450  	} else {
  3451  		proc.SessionInfo.Account = sysAccountName
  3452  		proc.SessionInfo.AccountId = sysAccountID
  3453  		proc.SessionInfo.RoleId = moAdminRoleID
  3454  		proc.SessionInfo.UserId = rootID
  3455  	}
  3456  	proc.SessionInfo.QueryId = ses.QueryId
  3457  	ses.txnCompileCtx.SetProcess(proc)
  3458  	cws, err := GetComputationWrapper(ses.GetDatabaseName(),
  3459  		sql,
  3460  		ses.GetUserName(),
  3461  		pu.StorageEngine,
  3462  		proc, ses)
  3463  	if err != nil {
  3464  		requestCtx = RecordParseErrorStatement(requestCtx, ses, proc, beginInstant, sql)
  3465  		retErr = err
  3466  		if _, ok := err.(*moerr.Error); !ok {
  3467  			retErr = moerr.NewParseError(requestCtx, err.Error())
  3468  		}
  3469  		logStatementStringStatus(requestCtx, ses, sql, fail, retErr)
  3470  		return retErr
  3471  	}
  3472  
  3473  	defer func() {
  3474  		ses.SetMysqlResultSet(nil)
  3475  	}()
  3476  
  3477  	var cmpBegin time.Time
  3478  	var ret interface{}
  3479  	var runner ComputationRunner
  3480  	var selfHandle bool
  3481  	var fromLoadData = false
  3482  	var txnErr error
  3483  	var rspLen uint64
  3484  	var prepareStmt *PrepareStmt
  3485  	var err2 error
  3486  	var columns []interface{}
  3487  	var mrs *MysqlResultSet
  3488  	canCache := true
  3489  	var loadLocalErrGroup *errgroup.Group
  3490  	var loadLocalWriter *io.PipeWriter
  3491  
  3492  	singleStatement := len(cws) == 1
  3493  	for i, cw := range cws {
  3494  		if cwft, ok := cw.(*TxnComputationWrapper); ok {
  3495  			if cwft.stmt.GetQueryType() == tree.QueryTypeDDL || cwft.stmt.GetQueryType() == tree.QueryTypeDCL ||
  3496  				cwft.stmt.GetQueryType() == tree.QueryTypeOth ||
  3497  				cwft.stmt.GetQueryType() == tree.QueryTypeTCL {
  3498  				if _, ok := cwft.stmt.(*tree.SetVar); !ok {
  3499  					ses.cleanCache()
  3500  				}
  3501  				canCache = false
  3502  			}
  3503  		}
  3504  
  3505  		ses.SetMysqlResultSet(&MysqlResultSet{})
  3506  		stmt := cw.GetAst()
  3507  		requestCtx = RecordStatement(requestCtx, ses, proc, cw, beginInstant, sql, singleStatement)
  3508  		tenant := ses.GetTenantName(stmt)
  3509  		//skip PREPARE statement here
  3510  		if ses.GetTenantInfo() != nil && !IsPrepareStatement(stmt) {
  3511  			err = authenticateUserCanExecuteStatement(requestCtx, ses, stmt)
  3512  			if err != nil {
  3513  				logStatementStatus(requestCtx, ses, stmt, fail, err)
  3514  				return err
  3515  			}
  3516  		}
  3517  
  3518  		/*
  3519  				if it is in an active or multi-statement transaction, we check the type of the statement.
  3520  				Then we decide that if we can execute the statement.
  3521  
  3522  			If we check the active transaction, it will generate the case below.
  3523  			case:
  3524  			set autocommit = 0;  <- no active transaction
  3525  			                     <- no active transaction
  3526  			drop table test1;    <- no active transaction, no error
  3527  			                     <- has active transaction
  3528  			drop table test1;    <- has active transaction, error
  3529  			                     <- has active transaction
  3530  		*/
  3531  		if ses.InActiveTransaction() {
  3532  			err = mce.canExecuteStatementInUncommittedTransaction(requestCtx, stmt)
  3533  			if err != nil {
  3534  				logStatementStatus(requestCtx, ses, stmt, fail, err)
  3535  				return err
  3536  			}
  3537  		}
  3538  
  3539  		//check transaction states
  3540  		switch stmt.(type) {
  3541  		case *tree.BeginTransaction:
  3542  			err = ses.TxnBegin()
  3543  			if err != nil {
  3544  				goto handleFailed
  3545  			}
  3546  			RecordStatementTxnID(requestCtx, ses)
  3547  		case *tree.CommitTransaction:
  3548  			err = ses.TxnCommit()
  3549  			if err != nil {
  3550  				goto handleFailed
  3551  			}
  3552  		case *tree.RollbackTransaction:
  3553  			err = ses.TxnRollback()
  3554  			if err != nil {
  3555  				goto handleFailed
  3556  			}
  3557  		}
  3558  
  3559  		switch st := stmt.(type) {
  3560  		case *tree.Select:
  3561  			if st.Ep != nil {
  3562  				ses.SetExportParam(st.Ep)
  3563  			}
  3564  		}
  3565  
  3566  		selfHandle = false
  3567  		ses.GetTxnCompileCtx().SetQueryType(TXN_DEFAULT)
  3568  
  3569  		switch st := stmt.(type) {
  3570  		case *tree.BeginTransaction, *tree.CommitTransaction, *tree.RollbackTransaction:
  3571  			selfHandle = true
  3572  		case *tree.SetRole:
  3573  			selfHandle = true
  3574  			ses.InvalidatePrivilegeCache()
  3575  			//switch role
  3576  			err = mce.handleSwitchRole(requestCtx, st)
  3577  			if err != nil {
  3578  				goto handleFailed
  3579  			}
  3580  		case *tree.Use:
  3581  			selfHandle = true
  3582  			//use database
  3583  			err = mce.handleChangeDB(requestCtx, st.Name)
  3584  			if err != nil {
  3585  				goto handleFailed
  3586  			}
  3587  			err = changeVersion(requestCtx, ses, st.Name)
  3588  			if err != nil {
  3589  				goto handleFailed
  3590  			}
  3591  		case *tree.MoDump:
  3592  			selfHandle = true
  3593  			//dump
  3594  			err = mce.handleDump(requestCtx, st)
  3595  			if err != nil {
  3596  				goto handleFailed
  3597  			}
  3598  		case *tree.DropDatabase:
  3599  			ses.InvalidatePrivilegeCache()
  3600  			// if the droped database is the same as the one in use, database must be reseted to empty.
  3601  			if string(st.Name) == ses.GetDatabaseName() {
  3602  				ses.SetDatabaseName("")
  3603  			}
  3604  		case *tree.Import:
  3605  			fromLoadData = true
  3606  			selfHandle = true
  3607  			err = mce.handleLoadData(requestCtx, proc, st)
  3608  			if err != nil {
  3609  				goto handleFailed
  3610  			}
  3611  		case *tree.PrepareStmt:
  3612  			selfHandle = true
  3613  			prepareStmt, err = mce.handlePrepareStmt(requestCtx, st)
  3614  			if err != nil {
  3615  				goto handleFailed
  3616  			}
  3617  			err = authenticateUserCanExecutePrepareOrExecute(requestCtx, ses, prepareStmt.PrepareStmt, prepareStmt.PreparePlan.GetDcl().GetPrepare().GetPlan())
  3618  			if err != nil {
  3619  				goto handleFailed
  3620  			}
  3621  		case *tree.PrepareString:
  3622  			selfHandle = true
  3623  			prepareStmt, err = mce.handlePrepareString(requestCtx, st)
  3624  			if err != nil {
  3625  				goto handleFailed
  3626  			}
  3627  			err = authenticateUserCanExecutePrepareOrExecute(requestCtx, ses, prepareStmt.PrepareStmt, prepareStmt.PreparePlan.GetDcl().GetPrepare().GetPlan())
  3628  			if err != nil {
  3629  				goto handleFailed
  3630  			}
  3631  		case *tree.Deallocate:
  3632  			selfHandle = true
  3633  			err = mce.handleDeallocate(requestCtx, st)
  3634  			if err != nil {
  3635  				goto handleFailed
  3636  			}
  3637  		case *tree.Reset:
  3638  			selfHandle = true
  3639  			err = mce.handleReset(requestCtx, st)
  3640  			if err != nil {
  3641  				goto handleFailed
  3642  			}
  3643  		case *tree.SetVar:
  3644  			selfHandle = true
  3645  			err = mce.handleSetVar(requestCtx, st)
  3646  			if err != nil {
  3647  				goto handleFailed
  3648  			}
  3649  		case *tree.ShowVariables:
  3650  			selfHandle = true
  3651  			err = mce.handleShowVariables(st, proc)
  3652  			if err != nil {
  3653  				goto handleFailed
  3654  			}
  3655  		case *tree.ShowErrors, *tree.ShowWarnings:
  3656  			selfHandle = true
  3657  			err = mce.handleShowErrors()
  3658  			if err != nil {
  3659  				goto handleFailed
  3660  			}
  3661  		case *tree.AnalyzeStmt:
  3662  			selfHandle = true
  3663  			if err = mce.handleAnalyzeStmt(requestCtx, st); err != nil {
  3664  				goto handleFailed
  3665  			}
  3666  		case *tree.ExplainStmt:
  3667  			selfHandle = true
  3668  			if err = mce.handleExplainStmt(requestCtx, st); err != nil {
  3669  				goto handleFailed
  3670  			}
  3671  		case *tree.ExplainAnalyze:
  3672  			ses.SetData(nil)
  3673  			switch st.Statement.(type) {
  3674  			case *tree.Delete:
  3675  				ses.GetTxnCompileCtx().SetQueryType(TXN_DELETE)
  3676  			case *tree.Update:
  3677  				ses.GetTxnCompileCtx().SetQueryType(TXN_UPDATE)
  3678  			default:
  3679  				ses.GetTxnCompileCtx().SetQueryType(TXN_DEFAULT)
  3680  			}
  3681  		case *tree.ShowColumns:
  3682  			ses.SetShowStmtType(ShowColumns)
  3683  			ses.SetData(nil)
  3684  		case *tree.ShowTableStatus:
  3685  			ses.SetShowStmtType(ShowTableStatus)
  3686  			ses.SetData(nil)
  3687  		case *tree.Delete:
  3688  			ses.GetTxnCompileCtx().SetQueryType(TXN_DELETE)
  3689  		case *tree.Update:
  3690  			ses.GetTxnCompileCtx().SetQueryType(TXN_UPDATE)
  3691  		case *InternalCmdFieldList:
  3692  			selfHandle = true
  3693  			if err = mce.handleCmdFieldList(requestCtx, st); err != nil {
  3694  				goto handleFailed
  3695  			}
  3696  		case *tree.CreateAccount:
  3697  			selfHandle = true
  3698  			ses.InvalidatePrivilegeCache()
  3699  			if err = mce.handleCreateAccount(requestCtx, st); err != nil {
  3700  				goto handleFailed
  3701  			}
  3702  		case *tree.DropAccount:
  3703  			selfHandle = true
  3704  			ses.InvalidatePrivilegeCache()
  3705  			if err = mce.handleDropAccount(requestCtx, st); err != nil {
  3706  				goto handleFailed
  3707  			}
  3708  		case *tree.AlterAccount:
  3709  			ses.InvalidatePrivilegeCache()
  3710  			selfHandle = true
  3711  			if err = mce.handleAlterAccount(requestCtx, st); err != nil {
  3712  				goto handleFailed
  3713  			}
  3714  		case *tree.AlterDataBaseConfig:
  3715  			ses.InvalidatePrivilegeCache()
  3716  			selfHandle = true
  3717  			if st.IsAccountLevel {
  3718  				if err = mce.handleAlterAccountConfig(requestCtx, st); err != nil {
  3719  					goto handleFailed
  3720  				}
  3721  			} else {
  3722  				if err = mce.handleAlterDataBaseConfig(requestCtx, st); err != nil {
  3723  					goto handleFailed
  3724  				}
  3725  			}
  3726  		case *tree.CreateUser:
  3727  			selfHandle = true
  3728  			ses.InvalidatePrivilegeCache()
  3729  			if err = mce.handleCreateUser(requestCtx, st); err != nil {
  3730  				goto handleFailed
  3731  			}
  3732  		case *tree.DropUser:
  3733  			selfHandle = true
  3734  			ses.InvalidatePrivilegeCache()
  3735  			if err = mce.handleDropUser(requestCtx, st); err != nil {
  3736  				goto handleFailed
  3737  			}
  3738  		case *tree.AlterView:
  3739  			ses.InvalidatePrivilegeCache()
  3740  		case *tree.AlterUser: //TODO
  3741  			ses.InvalidatePrivilegeCache()
  3742  		case *tree.CreateRole:
  3743  			selfHandle = true
  3744  			ses.InvalidatePrivilegeCache()
  3745  			if err = mce.handleCreateRole(requestCtx, st); err != nil {
  3746  				goto handleFailed
  3747  			}
  3748  		case *tree.DropRole:
  3749  			selfHandle = true
  3750  			ses.InvalidatePrivilegeCache()
  3751  			if err = mce.handleDropRole(requestCtx, st); err != nil {
  3752  				goto handleFailed
  3753  			}
  3754  		case *tree.CreateFunction:
  3755  			selfHandle = true
  3756  			if err = mce.handleCreateFunction(requestCtx, st); err != nil {
  3757  				goto handleFailed
  3758  			}
  3759  		case *tree.DropFunction:
  3760  			selfHandle = true
  3761  			if err = mce.handleDropFunction(requestCtx, st); err != nil {
  3762  				goto handleFailed
  3763  			}
  3764  		case *tree.Grant:
  3765  			selfHandle = true
  3766  			ses.InvalidatePrivilegeCache()
  3767  			switch st.Typ {
  3768  			case tree.GrantTypeRole:
  3769  				if err = mce.handleGrantRole(requestCtx, &st.GrantRole); err != nil {
  3770  					goto handleFailed
  3771  				}
  3772  			case tree.GrantTypePrivilege:
  3773  				if err = mce.handleGrantPrivilege(requestCtx, &st.GrantPrivilege); err != nil {
  3774  					goto handleFailed
  3775  				}
  3776  			}
  3777  		case *tree.Revoke:
  3778  			selfHandle = true
  3779  			ses.InvalidatePrivilegeCache()
  3780  			switch st.Typ {
  3781  			case tree.RevokeTypeRole:
  3782  				if err = mce.handleRevokeRole(requestCtx, &st.RevokeRole); err != nil {
  3783  					goto handleFailed
  3784  				}
  3785  			case tree.RevokeTypePrivilege:
  3786  				if err = mce.handleRevokePrivilege(requestCtx, &st.RevokePrivilege); err != nil {
  3787  					goto handleFailed
  3788  				}
  3789  			}
  3790  		case *tree.Kill:
  3791  			selfHandle = true
  3792  			ses.InvalidatePrivilegeCache()
  3793  			if err = mce.handleKill(requestCtx, st); err != nil {
  3794  				goto handleFailed
  3795  			}
  3796  		case *tree.ShowAccounts:
  3797  			selfHandle = true
  3798  			if err = mce.handleShowAccounts(requestCtx, st); err != nil {
  3799  				goto handleFailed
  3800  			}
  3801  		case *tree.Load:
  3802  			if st.Local {
  3803  				proc.LoadLocalReader, loadLocalWriter = io.Pipe()
  3804  			}
  3805  		}
  3806  
  3807  		if selfHandle {
  3808  			goto handleSucceeded
  3809  		}
  3810  		if err = cw.SetDatabaseName(ses.GetDatabaseName()); err != nil {
  3811  			goto handleFailed
  3812  		}
  3813  
  3814  		cmpBegin = time.Now()
  3815  
  3816  		if ret, err = cw.Compile(requestCtx, ses, ses.GetOutputCallback()); err != nil {
  3817  			goto handleFailed
  3818  		}
  3819  		stmt = cw.GetAst()
  3820  		// reset some special stmt for execute statement
  3821  		switch st := stmt.(type) {
  3822  		case *tree.SetVar:
  3823  			err = mce.handleSetVar(requestCtx, st)
  3824  			if err != nil {
  3825  				goto handleFailed
  3826  			} else {
  3827  				goto handleSucceeded
  3828  			}
  3829  		case *tree.ShowVariables:
  3830  			err = mce.handleShowVariables(st, proc)
  3831  			if err != nil {
  3832  				goto handleFailed
  3833  			} else {
  3834  				goto handleSucceeded
  3835  			}
  3836  		case *tree.ShowErrors, *tree.ShowWarnings:
  3837  			err = mce.handleShowErrors()
  3838  			if err != nil {
  3839  				goto handleFailed
  3840  			} else {
  3841  				goto handleSucceeded
  3842  			}
  3843  		}
  3844  
  3845  		runner = ret.(ComputationRunner)
  3846  
  3847  		logInfof(ses.GetConciseProfile(), "time of Exec.Build : %s", time.Since(cmpBegin).String())
  3848  
  3849  		mrs = ses.GetMysqlResultSet()
  3850  		// cw.Compile might rewrite sql, here we fetch the latest version
  3851  		switch statement := cw.GetAst().(type) {
  3852  		//produce result set
  3853  		case *tree.Select,
  3854  			*tree.ShowCreateTable, *tree.ShowCreateDatabase, *tree.ShowTables, *tree.ShowDatabases, *tree.ShowColumns,
  3855  			*tree.ShowProcessList, *tree.ShowStatus, *tree.ShowTableStatus, *tree.ShowGrants,
  3856  			*tree.ShowIndex, *tree.ShowCreateView, *tree.ShowTarget, *tree.ShowCollation, *tree.ValuesStatement,
  3857  			*tree.ExplainFor, *tree.ExplainStmt, *tree.ShowTableNumber, *tree.ShowColumnNumber, *tree.ShowTableValues, *tree.ShowLocks, *tree.ShowNodeList, *tree.ShowFunctionStatus:
  3858  			columns, err = cw.GetColumns()
  3859  			if err != nil {
  3860  				logErrorf(ses.GetConciseProfile(), "GetColumns from Computation handler failed. error: %v", err)
  3861  				goto handleFailed
  3862  			}
  3863  			if c, ok := cw.(*TxnComputationWrapper); ok {
  3864  				ses.rs = &plan.ResultColDef{ResultCols: plan2.GetResultColumnsFromPlan(c.plan)}
  3865  			}
  3866  			/*
  3867  				Step 1 : send column count and column definition.
  3868  			*/
  3869  			//send column count
  3870  			colCnt := uint64(len(columns))
  3871  			err = proto.SendColumnCountPacket(colCnt)
  3872  			if err != nil {
  3873  				goto handleFailed
  3874  			}
  3875  			//send columns
  3876  			//column_count * Protocol::ColumnDefinition packets
  3877  			cmd := ses.GetCmd()
  3878  			for _, c := range columns {
  3879  				mysqlc := c.(Column)
  3880  				mrs.AddColumn(mysqlc)
  3881  
  3882  				//logutil.Infof("doComQuery col name %v type %v ",col.Name(),col.ColumnType())
  3883  				/*
  3884  					mysql COM_QUERY response: send the column definition per column
  3885  				*/
  3886  				err = proto.SendColumnDefinitionPacket(requestCtx, mysqlc, int(cmd))
  3887  				if err != nil {
  3888  					goto handleFailed
  3889  				}
  3890  			}
  3891  
  3892  			/*
  3893  				mysql COM_QUERY response: End after the column has been sent.
  3894  				send EOF packet
  3895  			*/
  3896  			err = proto.SendEOFPacketIf(0, 0)
  3897  			if err != nil {
  3898  				goto handleFailed
  3899  			}
  3900  
  3901  			runBegin := time.Now()
  3902  			/*
  3903  				Step 2: Start pipeline
  3904  				Producing the data row and sending the data row
  3905  			*/
  3906  			ep := ses.GetExportParam()
  3907  			if ep.Outfile {
  3908  				ep.DefaultBufSize = pu.SV.ExportDataDefaultFlushSize
  3909  				initExportFileParam(ep, mrs)
  3910  				if err = openNewFile(requestCtx, ep, mrs); err != nil {
  3911  					goto handleFailed
  3912  				}
  3913  			}
  3914  			if err = runner.Run(0); err != nil {
  3915  				goto handleFailed
  3916  			}
  3917  
  3918  			switch ses.GetShowStmtType() {
  3919  			case ShowColumns:
  3920  				if err = handleShowColumns(ses, statement.(*tree.ShowColumns)); err != nil {
  3921  					goto handleFailed
  3922  				}
  3923  			case ShowTableStatus:
  3924  				if err = handleShowTableStatus(ses, statement.(*tree.ShowTableStatus), proc); err != nil {
  3925  					goto handleFailed
  3926  				}
  3927  			}
  3928  
  3929  			if ep.Outfile {
  3930  				if err = ep.Writer.Flush(); err != nil {
  3931  					goto handleFailed
  3932  				}
  3933  				if err = ep.File.Close(); err != nil {
  3934  					goto handleFailed
  3935  				}
  3936  			}
  3937  
  3938  			logInfof(ses.GetConciseProfile(), "time of Exec.Run : %s", time.Since(runBegin).String())
  3939  
  3940  			/*
  3941  				Step 3: Say goodbye
  3942  				mysql COM_QUERY response: End after the data row has been sent.
  3943  				After all row data has been sent, it sends the EOF or OK packet.
  3944  			*/
  3945  			err = proto.sendEOFOrOkPacket(0, 0)
  3946  			if err != nil {
  3947  				goto handleFailed
  3948  			}
  3949  
  3950  			/*
  3951  				Step 4: Serialize the execution plan by json
  3952  			*/
  3953  			if cwft, ok := cw.(*TxnComputationWrapper); ok {
  3954  				_ = cwft.RecordExecPlan(requestCtx)
  3955  			}
  3956  		//just status, no result set
  3957  		case *tree.CreateTable, *tree.DropTable, *tree.CreateDatabase, *tree.DropDatabase,
  3958  			*tree.CreateIndex, *tree.DropIndex,
  3959  			*tree.CreateView, *tree.DropView,
  3960  			*tree.AlterView,
  3961  			*tree.Insert, *tree.Update,
  3962  			*tree.BeginTransaction, *tree.CommitTransaction, *tree.RollbackTransaction,
  3963  			*tree.SetVar,
  3964  			*tree.Load,
  3965  			*tree.CreateUser, *tree.DropUser, *tree.AlterUser,
  3966  			*tree.CreateRole, *tree.DropRole,
  3967  			*tree.Revoke, *tree.Grant,
  3968  			*tree.SetDefaultRole, *tree.SetRole, *tree.SetPassword,
  3969  			*tree.Delete, *tree.TruncateTable:
  3970  			//change privilege
  3971  			switch cw.GetAst().(type) {
  3972  			case *tree.DropTable, *tree.DropDatabase, *tree.DropIndex, *tree.DropView,
  3973  				*tree.CreateUser, *tree.DropUser, *tree.AlterUser,
  3974  				*tree.CreateRole, *tree.DropRole,
  3975  				*tree.Revoke, *tree.Grant,
  3976  				*tree.SetDefaultRole, *tree.SetRole:
  3977  				ses.InvalidatePrivilegeCache()
  3978  			}
  3979  			runBegin := time.Now()
  3980  			/*
  3981  				Step 1: Start
  3982  			*/
  3983  
  3984  			if st, ok := cw.GetAst().(*tree.Load); ok {
  3985  				if st.Local {
  3986  					loadLocalErrGroup = new(errgroup.Group)
  3987  					loadLocalErrGroup.Go(func() error {
  3988  						return mce.processLoadLocal(proc.Ctx, st.Param, loadLocalWriter)
  3989  					})
  3990  				}
  3991  			}
  3992  
  3993  			if err = runner.Run(0); err != nil {
  3994  				if loadLocalErrGroup != nil { // release resources
  3995  					err2 := proc.LoadLocalReader.Close()
  3996  					if err2 != nil {
  3997  						logErrorf(ses.GetConciseProfile(), "processLoadLocal reader close failed: %s", err2.Error())
  3998  					}
  3999  					err2 = loadLocalErrGroup.Wait() // executor failed, but processLoadLocal is still running, wait for it
  4000  					if err2 != nil {
  4001  						logErrorf(ses.GetConciseProfile(), "processLoadLocal goroutine failed: %s", err2.Error())
  4002  					}
  4003  				}
  4004  				goto handleFailed
  4005  			}
  4006  
  4007  			if loadLocalErrGroup != nil {
  4008  				if err = loadLocalErrGroup.Wait(); err != nil { //executor success, but processLoadLocal goroutine failed
  4009  					goto handleFailed
  4010  				}
  4011  			}
  4012  
  4013  			logInfof(ses.GetConciseProfile(), "time of Exec.Run : %s", time.Since(runBegin).String())
  4014  
  4015  			rspLen = cw.GetAffectedRows()
  4016  			echoTime := time.Now()
  4017  
  4018  			logInfof(ses.GetConciseProfile(), "time of SendResponse %s", time.Since(echoTime).String())
  4019  
  4020  			/*
  4021  				Step 4: Serialize the execution plan by json
  4022  			*/
  4023  			if cwft, ok := cw.(*TxnComputationWrapper); ok {
  4024  				_ = cwft.RecordExecPlan(requestCtx)
  4025  			}
  4026  		case *tree.ExplainAnalyze:
  4027  			explainColName := "QUERY PLAN"
  4028  			columns, err = GetExplainColumns(requestCtx, explainColName)
  4029  			if err != nil {
  4030  				logErrorf(ses.GetConciseProfile(), "GetColumns from ExplainColumns handler failed, error: %v", err)
  4031  				goto handleFailed
  4032  			}
  4033  			/*
  4034  				Step 1 : send column count and column definition.
  4035  			*/
  4036  			//send column count
  4037  			colCnt := uint64(len(columns))
  4038  			err = proto.SendColumnCountPacket(colCnt)
  4039  			if err != nil {
  4040  				goto handleFailed
  4041  			}
  4042  			//send columns
  4043  			//column_count * Protocol::ColumnDefinition packets
  4044  			cmd := ses.GetCmd()
  4045  			for _, c := range columns {
  4046  				mysqlc := c.(Column)
  4047  				mrs.AddColumn(mysqlc)
  4048  				/*
  4049  					mysql COM_QUERY response: send the column definition per column
  4050  				*/
  4051  				err = proto.SendColumnDefinitionPacket(requestCtx, mysqlc, int(cmd))
  4052  				if err != nil {
  4053  					goto handleFailed
  4054  				}
  4055  			}
  4056  			/*
  4057  				mysql COM_QUERY response: End after the column has been sent.
  4058  				send EOF packet
  4059  			*/
  4060  			err = proto.SendEOFPacketIf(0, 0)
  4061  			if err != nil {
  4062  				goto handleFailed
  4063  			}
  4064  
  4065  			runBegin := time.Now()
  4066  			/*
  4067  				Step 1: Start
  4068  			*/
  4069  			if err = runner.Run(0); err != nil {
  4070  				goto handleFailed
  4071  			}
  4072  
  4073  			logInfof(ses.GetConciseProfile(), "time of Exec.Run : %s", time.Since(runBegin).String())
  4074  
  4075  			if cwft, ok := cw.(*TxnComputationWrapper); ok {
  4076  				queryPlan := cwft.plan
  4077  				// generator query explain
  4078  				explainQuery := explain.NewExplainQueryImpl(queryPlan.GetQuery())
  4079  
  4080  				// build explain data buffer
  4081  				buffer := explain.NewExplainDataBuffer()
  4082  				var option *explain.ExplainOptions
  4083  				option, err = getExplainOption(requestCtx, statement.Options)
  4084  				if err != nil {
  4085  					goto handleFailed
  4086  				}
  4087  
  4088  				err = explainQuery.ExplainPlan(requestCtx, buffer, option)
  4089  				if err != nil {
  4090  					goto handleFailed
  4091  				}
  4092  
  4093  				err = buildMoExplainQuery(explainColName, buffer, ses, getDataFromPipeline)
  4094  				if err != nil {
  4095  					goto handleFailed
  4096  				}
  4097  
  4098  				/*
  4099  					Step 3: Say goodbye
  4100  					mysql COM_QUERY response: End after the data row has been sent.
  4101  					After all row data has been sent, it sends the EOF or OK packet.
  4102  				*/
  4103  				err = proto.sendEOFOrOkPacket(0, 0)
  4104  				if err != nil {
  4105  					goto handleFailed
  4106  				}
  4107  			}
  4108  		}
  4109  	handleSucceeded:
  4110  		//load data handle txn failure internally
  4111  		incStatementCounter(tenant, stmt)
  4112  		if !fromLoadData {
  4113  			txnErr = ses.TxnCommitSingleStatement(stmt)
  4114  			if txnErr != nil {
  4115  				logStatementStatus(requestCtx, ses, stmt, fail, txnErr)
  4116  				return txnErr
  4117  			}
  4118  		}
  4119  		switch stmt.(type) {
  4120  		case *tree.CreateTable, *tree.DropTable,
  4121  			*tree.CreateIndex, *tree.DropIndex, *tree.Insert, *tree.Update,
  4122  			*tree.CreateView, *tree.DropView, *tree.AlterView, *tree.Load, *tree.MoDump,
  4123  			*tree.CreateAccount, *tree.DropAccount, *tree.AlterAccount, *tree.AlterDataBaseConfig,
  4124  			*tree.CreateFunction, *tree.DropFunction,
  4125  			*tree.CreateUser, *tree.DropUser, *tree.AlterUser,
  4126  			*tree.CreateRole, *tree.DropRole, *tree.Revoke, *tree.Grant,
  4127  			*tree.SetDefaultRole, *tree.SetRole, *tree.SetPassword, *tree.Delete, *tree.TruncateTable, *tree.Use,
  4128  			*tree.BeginTransaction, *tree.CommitTransaction, *tree.RollbackTransaction:
  4129  			resp := mce.setResponse(i, len(cws), rspLen)
  4130  			if _, ok := stmt.(*tree.Insert); ok {
  4131  				resp.lastInsertId = proc.GetLastInsertID()
  4132  				if proc.GetLastInsertID() != 0 {
  4133  					ses.SetLastInsertID(proc.GetLastInsertID())
  4134  				}
  4135  			}
  4136  			if err2 = mce.GetSession().GetMysqlProtocol().SendResponse(requestCtx, resp); err2 != nil {
  4137  				retErr = moerr.NewInternalError(requestCtx, "routine send response failed. error:%v ", err2)
  4138  				logStatementStatus(requestCtx, ses, stmt, fail, retErr)
  4139  				return retErr
  4140  			}
  4141  
  4142  		case *tree.CreateDatabase:
  4143  			insertRecordToMoMysqlCompatbilityMode(requestCtx, ses, stmt)
  4144  			resp := mce.setResponse(i, len(cws), rspLen)
  4145  			if err2 = mce.GetSession().GetMysqlProtocol().SendResponse(requestCtx, resp); err2 != nil {
  4146  				retErr = moerr.NewInternalError(requestCtx, "routine send response failed. error:%v ", err2)
  4147  				logStatementStatus(requestCtx, ses, stmt, fail, retErr)
  4148  				return retErr
  4149  			}
  4150  
  4151  		case *tree.DropDatabase:
  4152  			deleteRecordToMoMysqlCompatbilityMode(requestCtx, ses, stmt)
  4153  			resp := mce.setResponse(i, len(cws), rspLen)
  4154  			if err2 = mce.GetSession().GetMysqlProtocol().SendResponse(requestCtx, resp); err2 != nil {
  4155  				retErr = moerr.NewInternalError(requestCtx, "routine send response failed. error:%v ", err2)
  4156  				logStatementStatus(requestCtx, ses, stmt, fail, retErr)
  4157  				return retErr
  4158  			}
  4159  
  4160  		case *tree.PrepareStmt, *tree.PrepareString:
  4161  			if ses.GetCmd() == COM_STMT_PREPARE {
  4162  				if err2 = mce.GetSession().GetMysqlProtocol().SendPrepareResponse(requestCtx, prepareStmt); err2 != nil {
  4163  					retErr = moerr.NewInternalError(requestCtx, "routine send response failed. error:%v ", err2)
  4164  					logStatementStatus(requestCtx, ses, stmt, fail, retErr)
  4165  					return retErr
  4166  				}
  4167  			} else {
  4168  				resp := mce.setResponse(i, len(cws), rspLen)
  4169  				if err2 = mce.GetSession().GetMysqlProtocol().SendResponse(requestCtx, resp); err2 != nil {
  4170  					retErr = moerr.NewInternalError(requestCtx, "routine send response failed. error:%v ", err2)
  4171  					logStatementStatus(requestCtx, ses, stmt, fail, retErr)
  4172  					return retErr
  4173  				}
  4174  			}
  4175  
  4176  		case *tree.SetVar:
  4177  			resp := mce.setResponse(i, len(cws), rspLen)
  4178  			if err = proto.SendResponse(requestCtx, resp); err != nil {
  4179  				return moerr.NewInternalError(requestCtx, "routine send response failed. error:%v ", err)
  4180  			}
  4181  
  4182  		case *tree.Deallocate:
  4183  			//we will not send response in COM_STMT_CLOSE command
  4184  			if ses.GetCmd() != COM_STMT_CLOSE {
  4185  				resp := mce.setResponse(i, len(cws), rspLen)
  4186  				if err2 = mce.GetSession().GetMysqlProtocol().SendResponse(requestCtx, resp); err2 != nil {
  4187  					retErr = moerr.NewInternalError(requestCtx, "routine send response failed. error:%v ", err2)
  4188  					logStatementStatus(requestCtx, ses, stmt, fail, retErr)
  4189  					return retErr
  4190  				}
  4191  			}
  4192  
  4193  		case *tree.Reset:
  4194  			resp := mce.setResponse(i, len(cws), rspLen)
  4195  			if err2 = mce.GetSession().GetMysqlProtocol().SendResponse(requestCtx, resp); err2 != nil {
  4196  				retErr = moerr.NewInternalError(requestCtx, "routine send response failed. error:%v ", err2)
  4197  				logStatementStatus(requestCtx, ses, stmt, fail, retErr)
  4198  				return retErr
  4199  			}
  4200  		}
  4201  		logStatementStatus(requestCtx, ses, stmt, success, nil)
  4202  		goto handleNext
  4203  	handleFailed:
  4204  		incStatementCounter(tenant, stmt)
  4205  		incStatementErrorsCounter(tenant, stmt)
  4206  		/*
  4207  			Cases    | set Autocommit = 1/0 | BEGIN statement |
  4208  			---------------------------------------------------
  4209  			Case1      1                       Yes
  4210  			Case2      1                       No
  4211  			Case3      0                       Yes
  4212  			Case4      0                       No
  4213  			---------------------------------------------------
  4214  			update error message in Case1,Case3,Case4.
  4215  		*/
  4216  		if ses.InMultiStmtTransactionMode() && ses.InActiveTransaction() {
  4217  			ses.cleanCache()
  4218  			ses.SetOptionBits(OPTION_ATTACH_ABORT_TRANSACTION_ERROR)
  4219  		}
  4220  		logError(ses.GetConciseProfile(), err.Error())
  4221  		if !fromLoadData {
  4222  			txnErr = ses.TxnRollbackSingleStatement(stmt)
  4223  			if txnErr != nil {
  4224  				logStatementStatus(requestCtx, ses, stmt, fail, txnErr)
  4225  				return txnErr
  4226  			}
  4227  		}
  4228  		logStatementStatus(requestCtx, ses, stmt, fail, err)
  4229  		return err
  4230  	handleNext:
  4231  	} // end of for
  4232  
  4233  	if canCache && !ses.isCached(sql) {
  4234  		plans := make([]*plan.Plan, len(cws))
  4235  		stmts := make([]tree.Statement, len(cws))
  4236  		for i, cw := range cws {
  4237  			if cwft, ok := cw.(*TxnComputationWrapper); ok && checkNodeCanCache(cwft.plan) {
  4238  				plans[i] = cwft.plan
  4239  				stmts[i] = cwft.stmt
  4240  			} else {
  4241  				return nil
  4242  			}
  4243  		}
  4244  		ses.cachePlan(sql, stmts, plans)
  4245  	}
  4246  
  4247  	return nil
  4248  }
  4249  
  4250  func checkNodeCanCache(p *plan2.Plan) bool {
  4251  	if p == nil {
  4252  		return true
  4253  	}
  4254  	if q, ok := p.Plan.(*plan2.Plan_Query); ok {
  4255  		for _, node := range q.Query.Nodes {
  4256  			if node.NotCacheable {
  4257  				return false
  4258  			}
  4259  		}
  4260  	}
  4261  	return true
  4262  }
  4263  
  4264  // execute query. Currently, it is developing. Finally, it will replace the doComQuery.
  4265  func (mce *MysqlCmdExecutor) doComQueryInProgress(requestCtx context.Context, sql string) (retErr error) {
  4266  	var stmtExecs []StmtExecutor
  4267  	var err error
  4268  	beginInstant := time.Now()
  4269  	ses := mce.GetSession()
  4270  	ses.SetShowStmtType(NotShowStatement)
  4271  	proto := ses.GetMysqlProtocol()
  4272  	ses.SetSql(sql)
  4273  	ses.GetExportParam().Outfile = false
  4274  	pu := ses.GetParameterUnit()
  4275  	proc := process.New(
  4276  		requestCtx,
  4277  		ses.GetMemPool(),
  4278  		pu.TxnClient,
  4279  		ses.GetTxnHandler().GetTxnOperator(),
  4280  		pu.FileService,
  4281  		pu.GetClusterDetails,
  4282  	)
  4283  	proc.Id = mce.getNextProcessId()
  4284  	proc.Lim.Size = pu.SV.ProcessLimitationSize
  4285  	proc.Lim.BatchRows = pu.SV.ProcessLimitationBatchRows
  4286  	proc.Lim.PartitionRows = pu.SV.ProcessLimitationPartitionRows
  4287  	proc.SessionInfo = process.SessionInfo{
  4288  		User:              ses.GetUserName(),
  4289  		Host:              pu.SV.Host,
  4290  		ConnectionID:      uint64(proto.ConnectionID()),
  4291  		Database:          ses.GetDatabaseName(),
  4292  		Version:           pu.SV.ServerVersionPrefix + serverVersion.Load().(string),
  4293  		TimeZone:          ses.GetTimeZone(),
  4294  		StorageEngine:     pu.StorageEngine,
  4295  		AutoIncrCaches:    ses.GetAutoIncrCaches(),
  4296  		AutoIncrCacheSize: ses.pu.SV.AutoIncrCacheSize,
  4297  	}
  4298  
  4299  	if ses.GetTenantInfo() != nil {
  4300  		proc.SessionInfo.Account = ses.GetTenantInfo().GetTenant()
  4301  		proc.SessionInfo.AccountId = ses.GetTenantInfo().GetTenantID()
  4302  		proc.SessionInfo.RoleId = ses.GetTenantInfo().GetDefaultRoleID()
  4303  		proc.SessionInfo.UserId = ses.GetTenantInfo().GetUserID()
  4304  	} else {
  4305  		proc.SessionInfo.Account = sysAccountName
  4306  		proc.SessionInfo.AccountId = sysAccountID
  4307  		proc.SessionInfo.RoleId = moAdminRoleID
  4308  		proc.SessionInfo.UserId = rootID
  4309  	}
  4310  
  4311  	stmtExecs, err = GetStmtExecList(ses.GetDatabaseName(),
  4312  		sql,
  4313  		ses.GetUserName(),
  4314  		pu.StorageEngine,
  4315  		proc, ses)
  4316  	if err != nil {
  4317  		requestCtx = RecordParseErrorStatement(requestCtx, ses, proc, beginInstant, sql)
  4318  		retErr = moerr.NewParseError(requestCtx, err.Error())
  4319  		logStatementStringStatus(requestCtx, ses, sql, fail, retErr)
  4320  		return retErr
  4321  	}
  4322  
  4323  	singleStatement := len(stmtExecs) == 1
  4324  	for _, exec := range stmtExecs {
  4325  		err = Execute(requestCtx, ses, proc, exec, beginInstant, sql, singleStatement)
  4326  		if err != nil {
  4327  			return err
  4328  		}
  4329  	}
  4330  	return err
  4331  }
  4332  
  4333  func (mce *MysqlCmdExecutor) setResponse(cwIndex, cwsLen int, rspLen uint64) *Response {
  4334  
  4335  	//if the stmt has next stmt, should set the server status equals to 10
  4336  	if cwIndex < cwsLen-1 {
  4337  		return NewOkResponse(rspLen, 0, 0, SERVER_MORE_RESULTS_EXISTS, int(COM_QUERY), "")
  4338  	} else {
  4339  		return NewOkResponse(rspLen, 0, 0, 0, int(COM_QUERY), "")
  4340  	}
  4341  
  4342  }
  4343  
  4344  // ExecRequest the server execute the commands from the client following the mysql's routine
  4345  func (mce *MysqlCmdExecutor) ExecRequest(requestCtx context.Context, ses *Session, req *Request) (resp *Response, err error) {
  4346  	defer func() {
  4347  		if e := recover(); e != nil {
  4348  			moe, ok := e.(*moerr.Error)
  4349  			if !ok {
  4350  				err = moerr.ConvertPanicError(requestCtx, e)
  4351  				resp = NewGeneralErrorResponse(COM_QUERY, err)
  4352  			} else {
  4353  				resp = NewGeneralErrorResponse(COM_QUERY, moe)
  4354  			}
  4355  		}
  4356  	}()
  4357  
  4358  	var sql string
  4359  	logDebugf(ses.GetCompleteProfile(), "cmd %v", req.GetCmd())
  4360  	ses.SetCmd(req.GetCmd())
  4361  	doComQuery := mce.GetDoQueryFunc()
  4362  	switch req.GetCmd() {
  4363  	case COM_QUIT:
  4364  		/*resp = NewResponse(
  4365  			OkResponse,
  4366  			0,
  4367  			int(COM_QUIT),
  4368  			nil,
  4369  		)*/
  4370  		return resp, nil
  4371  	case COM_QUERY:
  4372  		var query = string(req.GetData().([]byte))
  4373  		mce.addSqlCount(1)
  4374  		logInfo(ses.GetConciseProfile(), "query trace", logutil.ConnectionIdField(ses.GetConnectionID()), logutil.QueryField(SubStringFromBegin(query, int(ses.GetParameterUnit().SV.LengthOfQueryPrinted))))
  4375  		err = doComQuery(requestCtx, query)
  4376  		if err != nil {
  4377  			resp = NewGeneralErrorResponse(COM_QUERY, err)
  4378  		}
  4379  		return resp, nil
  4380  	case COM_INIT_DB:
  4381  		var dbname = string(req.GetData().([]byte))
  4382  		mce.addSqlCount(1)
  4383  		query := "use `" + dbname + "`"
  4384  		err = doComQuery(requestCtx, query)
  4385  		if err != nil {
  4386  			resp = NewGeneralErrorResponse(COM_INIT_DB, err)
  4387  		}
  4388  
  4389  		return resp, nil
  4390  	case COM_FIELD_LIST:
  4391  		var payload = string(req.GetData().([]byte))
  4392  		mce.addSqlCount(1)
  4393  		query := makeCmdFieldListSql(payload)
  4394  		err = doComQuery(requestCtx, query)
  4395  		if err != nil {
  4396  			resp = NewGeneralErrorResponse(COM_FIELD_LIST, err)
  4397  		}
  4398  
  4399  		return resp, nil
  4400  	case COM_PING:
  4401  		resp = NewGeneralOkResponse(COM_PING)
  4402  
  4403  		return resp, nil
  4404  
  4405  	case COM_STMT_PREPARE:
  4406  		ses.SetCmd(COM_STMT_PREPARE)
  4407  		sql = string(req.GetData().([]byte))
  4408  		mce.addSqlCount(1)
  4409  
  4410  		// rewrite to "Prepare stmt_name from 'xxx'"
  4411  		newLastStmtID := ses.GenNewStmtId()
  4412  		newStmtName := getPrepareStmtName(newLastStmtID)
  4413  		sql = fmt.Sprintf("prepare %s from %s", newStmtName, sql)
  4414  		logInfo(ses.GetConciseProfile(), "query trace", logutil.ConnectionIdField(ses.GetConnectionID()), logutil.QueryField(sql))
  4415  
  4416  		err = doComQuery(requestCtx, sql)
  4417  		if err != nil {
  4418  			resp = NewGeneralErrorResponse(COM_STMT_PREPARE, err)
  4419  		}
  4420  		return resp, nil
  4421  
  4422  	case COM_STMT_EXECUTE:
  4423  		ses.SetCmd(COM_STMT_EXECUTE)
  4424  		data := req.GetData().([]byte)
  4425  		sql, err = mce.parseStmtExecute(requestCtx, data)
  4426  		if err != nil {
  4427  			return NewGeneralErrorResponse(COM_STMT_EXECUTE, err), nil
  4428  		}
  4429  		err = doComQuery(requestCtx, sql)
  4430  		if err != nil {
  4431  			resp = NewGeneralErrorResponse(COM_STMT_EXECUTE, err)
  4432  		}
  4433  		return resp, nil
  4434  
  4435  	case COM_STMT_CLOSE:
  4436  		data := req.GetData().([]byte)
  4437  
  4438  		// rewrite to "deallocate Prepare stmt_name"
  4439  		stmtID := binary.LittleEndian.Uint32(data[0:4])
  4440  		stmtName := getPrepareStmtName(stmtID)
  4441  		sql = fmt.Sprintf("deallocate prepare %s", stmtName)
  4442  		logInfo(ses.GetConciseProfile(), "query trace", logutil.ConnectionIdField(ses.GetConnectionID()), logutil.QueryField(sql))
  4443  
  4444  		err = doComQuery(requestCtx, sql)
  4445  		if err != nil {
  4446  			resp = NewGeneralErrorResponse(COM_STMT_CLOSE, err)
  4447  		}
  4448  		return resp, nil
  4449  
  4450  	case COM_STMT_RESET:
  4451  		data := req.GetData().([]byte)
  4452  
  4453  		//Payload of COM_STMT_RESET
  4454  		stmtID := binary.LittleEndian.Uint32(data[0:4])
  4455  		stmtName := getPrepareStmtName(stmtID)
  4456  		sql = fmt.Sprintf("reset prepare %s", stmtName)
  4457  		logInfo(ses.GetConciseProfile(), "query trace", logutil.ConnectionIdField(ses.GetConnectionID()), logutil.QueryField(sql))
  4458  		err = doComQuery(requestCtx, sql)
  4459  		if err != nil {
  4460  			resp = NewGeneralErrorResponse(COM_STMT_RESET, err)
  4461  		}
  4462  		return resp, nil
  4463  
  4464  	default:
  4465  		resp = NewGeneralErrorResponse(req.GetCmd(), moerr.NewInternalError(requestCtx, "unsupported command. 0x%x", req.GetCmd()))
  4466  	}
  4467  	return resp, nil
  4468  }
  4469  
  4470  func (mce *MysqlCmdExecutor) parseStmtExecute(requestCtx context.Context, data []byte) (string, error) {
  4471  	// see https://dev.mysql.com/doc/internals/en/com-stmt-execute.html
  4472  	pos := 0
  4473  	if len(data) < 4 {
  4474  		return "", moerr.NewInvalidInput(requestCtx, "sql command contains malformed packet")
  4475  	}
  4476  	stmtID := binary.LittleEndian.Uint32(data[0:4])
  4477  	pos += 4
  4478  
  4479  	stmtName := fmt.Sprintf("%s_%d", prefixPrepareStmtName, stmtID)
  4480  	ses := mce.GetSession()
  4481  	preStmt, err := ses.GetPrepareStmt(stmtName)
  4482  	if err != nil {
  4483  		return "", err
  4484  	}
  4485  	names, vars, err := ses.GetMysqlProtocol().ParseExecuteData(requestCtx, preStmt, data, pos)
  4486  	if err != nil {
  4487  		return "", err
  4488  	}
  4489  	sql := fmt.Sprintf("execute %s", stmtName)
  4490  	varStrings := make([]string, len(names))
  4491  	if len(names) > 0 {
  4492  		sql = sql + fmt.Sprintf(" using @%s", strings.Join(names, ",@"))
  4493  		for i := 0; i < len(names); i++ {
  4494  			varStrings[i] = fmt.Sprintf("%v", vars[i])
  4495  			err := ses.SetUserDefinedVar(names[i], vars[i])
  4496  			if err != nil {
  4497  				return "", err
  4498  			}
  4499  		}
  4500  	}
  4501  	logInfo(ses.GetConciseProfile(), "query trace", logutil.ConnectionIdField(ses.GetConnectionID()), logutil.QueryField(sql), logutil.VarsField(strings.Join(varStrings, " , ")))
  4502  	return sql, nil
  4503  }
  4504  
  4505  func (mce *MysqlCmdExecutor) SetCancelFunc(cancelFunc context.CancelFunc) {
  4506  	mce.mu.Lock()
  4507  	defer mce.mu.Unlock()
  4508  	mce.cancelRequestFunc = cancelFunc
  4509  }
  4510  
  4511  func (mce *MysqlCmdExecutor) Close() {}
  4512  
  4513  /*
  4514  StatementCanBeExecutedInUncommittedTransaction checks the statement can be executed in an active transaction.
  4515  */
  4516  func StatementCanBeExecutedInUncommittedTransaction(ses *Session, stmt tree.Statement) (bool, error) {
  4517  	switch st := stmt.(type) {
  4518  	//ddl statement
  4519  	case *tree.CreateTable, *tree.CreateDatabase, *tree.CreateIndex, *tree.CreateView, *tree.AlterView:
  4520  		return true, nil
  4521  		//dml statement
  4522  	case *tree.Insert, *tree.Update, *tree.Delete, *tree.Select, *tree.Load, *tree.MoDump, *tree.ValuesStatement:
  4523  		return true, nil
  4524  		//transaction
  4525  	case *tree.BeginTransaction, *tree.CommitTransaction, *tree.RollbackTransaction:
  4526  		return true, nil
  4527  		//show
  4528  	case *tree.ShowCreateTable,
  4529  		*tree.ShowCreateView,
  4530  		*tree.ShowCreateDatabase,
  4531  		*tree.ShowColumns,
  4532  		*tree.ShowDatabases,
  4533  		*tree.ShowTarget,
  4534  		*tree.ShowTableStatus,
  4535  		*tree.ShowGrants,
  4536  		*tree.ShowTables,
  4537  		*tree.ShowProcessList,
  4538  		*tree.ShowErrors,
  4539  		*tree.ShowWarnings,
  4540  		*tree.ShowCollation,
  4541  		*tree.ShowVariables,
  4542  		*tree.ShowStatus,
  4543  		*tree.ShowIndex,
  4544  		*tree.ShowFunctionStatus,
  4545  		*tree.ShowNodeList,
  4546  		*tree.ShowLocks,
  4547  		*tree.ShowTableNumber,
  4548  		*tree.ShowColumnNumber,
  4549  		*tree.ShowTableValues,
  4550  		*tree.ShowAccounts:
  4551  		return true, nil
  4552  		//others
  4553  	case *tree.ExplainStmt, *tree.ExplainAnalyze, *tree.ExplainFor, *InternalCmdFieldList:
  4554  		return true, nil
  4555  	case *tree.PrepareStmt:
  4556  		return StatementCanBeExecutedInUncommittedTransaction(ses, st.Stmt)
  4557  	case *tree.PrepareString:
  4558  		preStmt, err := mysql.ParseOne(ses.requestCtx, st.Sql)
  4559  		if err != nil {
  4560  			return false, err
  4561  		}
  4562  		return StatementCanBeExecutedInUncommittedTransaction(ses, preStmt)
  4563  	case *tree.Execute:
  4564  		preName := string(st.Name)
  4565  		preStmt, err := ses.GetPrepareStmt(preName)
  4566  		if err != nil {
  4567  			return false, err
  4568  		}
  4569  		return StatementCanBeExecutedInUncommittedTransaction(ses, preStmt.PrepareStmt)
  4570  	case *tree.Deallocate, *tree.Reset:
  4571  		return true, nil
  4572  	case *tree.Use:
  4573  		/*
  4574  			These statements can not be executed in an uncommitted transaction:
  4575  				USE SECONDARY ROLE { ALL | NONE }
  4576  				USE ROLE role;
  4577  		*/
  4578  		return !st.IsUseRole(), nil
  4579  	case *tree.DropTable, *tree.DropDatabase, *tree.DropIndex, *tree.DropView:
  4580  		//background transaction can execute the DROPxxx in one transaction
  4581  		return ses.IsBackgroundSession(), nil
  4582  	}
  4583  
  4584  	return false, nil
  4585  }
  4586  
  4587  // IsDDL checks the statement is the DDL statement.
  4588  func IsDDL(stmt tree.Statement) bool {
  4589  	switch stmt.(type) {
  4590  	case *tree.CreateTable, *tree.DropTable,
  4591  		*tree.CreateView, *tree.DropView, *tree.AlterView,
  4592  		*tree.CreateDatabase, *tree.DropDatabase,
  4593  		*tree.CreateIndex, *tree.DropIndex, *tree.TruncateTable:
  4594  		return true
  4595  	}
  4596  	return false
  4597  }
  4598  
  4599  // IsDropStatement checks the statement is the drop statement.
  4600  func IsDropStatement(stmt tree.Statement) bool {
  4601  	switch stmt.(type) {
  4602  	case *tree.DropDatabase, *tree.DropTable, *tree.DropView, *tree.DropIndex:
  4603  		return true
  4604  	}
  4605  	return false
  4606  }
  4607  
  4608  // IsAdministrativeStatement checks the statement is the administrative statement.
  4609  func IsAdministrativeStatement(stmt tree.Statement) bool {
  4610  	switch st := stmt.(type) {
  4611  	case *tree.CreateAccount, *tree.DropAccount, *tree.AlterAccount,
  4612  		*tree.CreateUser, *tree.DropUser, *tree.AlterUser,
  4613  		*tree.CreateRole, *tree.DropRole,
  4614  		*tree.Revoke, *tree.Grant,
  4615  		*tree.SetDefaultRole, *tree.SetRole, *tree.SetPassword:
  4616  		return true
  4617  	case *tree.Use:
  4618  		return st.IsUseRole()
  4619  	}
  4620  	return false
  4621  }
  4622  
  4623  // IsParameterModificationStatement checks the statement is the statement of parameter modification statement.
  4624  func IsParameterModificationStatement(stmt tree.Statement) bool {
  4625  	switch stmt.(type) {
  4626  	case *tree.SetVar:
  4627  		return true
  4628  	}
  4629  	return false
  4630  }
  4631  
  4632  // IsPrepareStatement checks the statement is the Prepare statement.
  4633  func IsPrepareStatement(stmt tree.Statement) bool {
  4634  	switch stmt.(type) {
  4635  	case *tree.PrepareStmt, *tree.PrepareString:
  4636  		return true
  4637  	}
  4638  	return false
  4639  }
  4640  
  4641  /*
  4642  NeedToBeCommittedInActiveTransaction checks the statement that need to be committed
  4643  in an active transaction.
  4644  
  4645  Currently, it includes the drop statement, the administration statement ,
  4646  
  4647  	the parameter modification statement.
  4648  */
  4649  func NeedToBeCommittedInActiveTransaction(stmt tree.Statement) bool {
  4650  	if stmt == nil {
  4651  		return false
  4652  	}
  4653  	return IsDropStatement(stmt) || IsAdministrativeStatement(stmt) || IsParameterModificationStatement(stmt)
  4654  }
  4655  
  4656  func NewMysqlCmdExecutor() *MysqlCmdExecutor {
  4657  	return &MysqlCmdExecutor{}
  4658  }
  4659  
  4660  /*
  4661  convert the type in computation engine to the type in mysql.
  4662  */
  4663  func convertEngineTypeToMysqlType(ctx context.Context, engineType types.T, col *MysqlColumn) error {
  4664  	switch engineType {
  4665  	case types.T_any:
  4666  		col.SetColumnType(defines.MYSQL_TYPE_NULL)
  4667  	case types.T_json:
  4668  		col.SetColumnType(defines.MYSQL_TYPE_JSON)
  4669  	case types.T_bool:
  4670  		col.SetColumnType(defines.MYSQL_TYPE_BOOL)
  4671  	case types.T_int8:
  4672  		col.SetColumnType(defines.MYSQL_TYPE_TINY)
  4673  	case types.T_uint8:
  4674  		col.SetColumnType(defines.MYSQL_TYPE_TINY)
  4675  		col.SetSigned(false)
  4676  	case types.T_int16:
  4677  		col.SetColumnType(defines.MYSQL_TYPE_SHORT)
  4678  	case types.T_uint16:
  4679  		col.SetColumnType(defines.MYSQL_TYPE_SHORT)
  4680  		col.SetSigned(false)
  4681  	case types.T_int32:
  4682  		col.SetColumnType(defines.MYSQL_TYPE_LONG)
  4683  	case types.T_uint32:
  4684  		col.SetColumnType(defines.MYSQL_TYPE_LONG)
  4685  		col.SetSigned(false)
  4686  	case types.T_int64:
  4687  		col.SetColumnType(defines.MYSQL_TYPE_LONGLONG)
  4688  	case types.T_uint64:
  4689  		col.SetColumnType(defines.MYSQL_TYPE_LONGLONG)
  4690  		col.SetSigned(false)
  4691  	case types.T_float32:
  4692  		col.SetColumnType(defines.MYSQL_TYPE_FLOAT)
  4693  	case types.T_float64:
  4694  		col.SetColumnType(defines.MYSQL_TYPE_DOUBLE)
  4695  	case types.T_char:
  4696  		col.SetColumnType(defines.MYSQL_TYPE_STRING)
  4697  	case types.T_varchar:
  4698  		col.SetColumnType(defines.MYSQL_TYPE_VARCHAR)
  4699  	case types.T_date:
  4700  		col.SetColumnType(defines.MYSQL_TYPE_DATE)
  4701  	case types.T_datetime:
  4702  		col.SetColumnType(defines.MYSQL_TYPE_DATETIME)
  4703  	case types.T_time:
  4704  		col.SetColumnType(defines.MYSQL_TYPE_TIME)
  4705  	case types.T_timestamp:
  4706  		col.SetColumnType(defines.MYSQL_TYPE_TIMESTAMP)
  4707  	case types.T_decimal64:
  4708  		col.SetColumnType(defines.MYSQL_TYPE_DECIMAL)
  4709  	case types.T_decimal128:
  4710  		col.SetColumnType(defines.MYSQL_TYPE_DECIMAL)
  4711  	case types.T_blob:
  4712  		col.SetColumnType(defines.MYSQL_TYPE_BLOB)
  4713  	case types.T_text:
  4714  		col.SetColumnType(defines.MYSQL_TYPE_TEXT)
  4715  	case types.T_uuid:
  4716  		col.SetColumnType(defines.MYSQL_TYPE_UUID)
  4717  	default:
  4718  		return moerr.NewInternalError(ctx, "RunWhileSend : unsupported type %d", engineType)
  4719  	}
  4720  	return nil
  4721  }
  4722  
  4723  func convertMysqlTextTypeToBlobType(col *MysqlColumn) {
  4724  	if col.ColumnType() == defines.MYSQL_TYPE_TEXT {
  4725  		col.SetColumnType(defines.MYSQL_TYPE_BLOB)
  4726  	}
  4727  }
  4728  
  4729  // build plan json when marhal plan error
  4730  func buildErrorJsonPlan(uuid uuid.UUID, errcode uint16, msg string) []byte {
  4731  	explainData := explain.ExplainData{
  4732  		Code:    errcode,
  4733  		Message: msg,
  4734  		Success: false,
  4735  		Uuid:    uuid.String(),
  4736  	}
  4737  	buffer := &bytes.Buffer{}
  4738  	encoder := json.NewEncoder(buffer)
  4739  	encoder.SetEscapeHTML(false)
  4740  	encoder.Encode(explainData)
  4741  	return buffer.Bytes()
  4742  }
  4743  
  4744  func serializePlanToJson(ctx context.Context, queryPlan *plan2.Plan, uuid uuid.UUID) (jsonBytes []byte, statsJonsBytes []byte, stats motrace.Statistic) {
  4745  	if queryPlan != nil && queryPlan.GetQuery() != nil {
  4746  		explainQuery := explain.NewExplainQueryImpl(queryPlan.GetQuery())
  4747  		options := &explain.ExplainOptions{
  4748  			Verbose: true,
  4749  			Analyze: true,
  4750  			Format:  explain.EXPLAIN_FORMAT_TEXT,
  4751  		}
  4752  		marshalPlan := explainQuery.BuildJsonPlan(ctx, uuid, options)
  4753  		stats.RowsRead, stats.BytesScan = marshalPlan.StatisticsRead()
  4754  		// data transform to json datastruct
  4755  		buffer := &bytes.Buffer{}
  4756  		encoder := json.NewEncoder(buffer)
  4757  		encoder.SetEscapeHTML(false)
  4758  		err := encoder.Encode(marshalPlan)
  4759  		if err != nil {
  4760  			moError := moerr.NewInternalError(ctx, "serialize plan to json error: %s", err.Error())
  4761  			jsonBytes = buildErrorJsonPlan(uuid, moError.ErrorCode(), moError.Error())
  4762  		} else {
  4763  			jsonBytes = buffer.Bytes()
  4764  		}
  4765  		// data transform Global to json
  4766  		if len(marshalPlan.Steps) > 0 {
  4767  			if len(marshalPlan.Steps) > 1 {
  4768  				logutil.Fatalf("need handle multi execPlan trees, cnt: %d", len(marshalPlan.Steps))
  4769  			}
  4770  			buffer := &bytes.Buffer{}
  4771  			encoder := json.NewEncoder(buffer)
  4772  			encoder.SetEscapeHTML(false)
  4773  			global := marshalPlan.Steps[0].GraphData.Global
  4774  			err = encoder.Encode(&global)
  4775  			if err != nil {
  4776  				statsJonsBytes = []byte(fmt.Sprintf(`{"code":200,"message":"%q"}`, err.Error()))
  4777  			} else {
  4778  				statsJonsBytes = buffer.Bytes()
  4779  			}
  4780  		}
  4781  	} else {
  4782  		jsonBytes = buildErrorJsonPlan(uuid, moerr.ErrWarn, "sql query no record execution plan")
  4783  	}
  4784  	return jsonBytes, statsJonsBytes, stats
  4785  }
  4786  
  4787  // SerializeExecPlan Serialize the execution plan by json
  4788  var SerializeExecPlan = func(ctx context.Context, plan any, uuid uuid.UUID) ([]byte, []byte, motrace.Statistic) {
  4789  	if plan == nil {
  4790  		return serializePlanToJson(ctx, nil, uuid)
  4791  	} else if queryPlan, ok := plan.(*plan2.Plan); !ok {
  4792  		moError := moerr.NewInternalError(ctx, "execPlan not type of plan2.Plan: %s", reflect.ValueOf(plan).Type().Name())
  4793  		return buildErrorJsonPlan(uuid, moError.ErrorCode(), moError.Error()), []byte{}, motrace.Statistic{}
  4794  	} else {
  4795  		// data transform to json dataStruct
  4796  		return serializePlanToJson(ctx, queryPlan, uuid)
  4797  	}
  4798  }
  4799  
  4800  func init() {
  4801  	motrace.SetDefaultSerializeExecPlan(SerializeExecPlan)
  4802  }
  4803  
  4804  func getAccountId(ctx context.Context) uint32 {
  4805  	var accountId uint32
  4806  
  4807  	if v := ctx.Value(defines.TenantIDKey{}); v != nil {
  4808  		accountId = v.(uint32)
  4809  	}
  4810  	return accountId
  4811  }
  4812  
  4813  func changeVersion(ctx context.Context, ses *Session, db string) error {
  4814  	var err error
  4815  	version, _ := GetVersionCompatbility(ctx, ses, db)
  4816  	if ses.GetTenantInfo() != nil {
  4817  		ses.GetTenantInfo().SetVersion(version)
  4818  	}
  4819  	return err
  4820  }