github.com/matrixorigin/matrixone@v1.2.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  	"errors"
    23  	"fmt"
    24  	"io"
    25  	gotrace "runtime/trace"
    26  	"sort"
    27  	"strconv"
    28  	"strings"
    29  	"sync"
    30  	"time"
    31  
    32  	"github.com/confluentinc/confluent-kafka-go/v2/kafka"
    33  	"github.com/fagongzi/goetty/v2"
    34  	"github.com/google/uuid"
    35  	"go.uber.org/zap"
    36  
    37  	"github.com/matrixorigin/matrixone/pkg/clusterservice"
    38  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    39  	"github.com/matrixorigin/matrixone/pkg/common/runtime"
    40  	"github.com/matrixorigin/matrixone/pkg/common/util"
    41  	"github.com/matrixorigin/matrixone/pkg/container/batch"
    42  	"github.com/matrixorigin/matrixone/pkg/container/types"
    43  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    44  	"github.com/matrixorigin/matrixone/pkg/defines"
    45  	"github.com/matrixorigin/matrixone/pkg/frontend/constant"
    46  	"github.com/matrixorigin/matrixone/pkg/logutil"
    47  	"github.com/matrixorigin/matrixone/pkg/pb/metadata"
    48  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    49  	"github.com/matrixorigin/matrixone/pkg/pb/timestamp"
    50  	"github.com/matrixorigin/matrixone/pkg/sql/colexec"
    51  	"github.com/matrixorigin/matrixone/pkg/sql/compile"
    52  	"github.com/matrixorigin/matrixone/pkg/sql/parsers"
    53  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect"
    54  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect/mysql"
    55  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
    56  	plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan"
    57  	"github.com/matrixorigin/matrixone/pkg/sql/plan/explain"
    58  	"github.com/matrixorigin/matrixone/pkg/txn/client"
    59  	txnTrace "github.com/matrixorigin/matrixone/pkg/txn/trace"
    60  	"github.com/matrixorigin/matrixone/pkg/util/metric"
    61  	v2 "github.com/matrixorigin/matrixone/pkg/util/metric/v2"
    62  	"github.com/matrixorigin/matrixone/pkg/util/trace"
    63  	"github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace"
    64  	"github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace/statistic"
    65  	"github.com/matrixorigin/matrixone/pkg/vm/engine"
    66  	"github.com/matrixorigin/matrixone/pkg/vm/engine/disttae"
    67  	"github.com/matrixorigin/matrixone/pkg/vm/engine/disttae/route"
    68  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    69  )
    70  
    71  func createDropDatabaseErrorInfo() string {
    72  	return "CREATE/DROP of database is not supported in transactions"
    73  }
    74  
    75  func onlyCreateStatementErrorInfo() string {
    76  	return "Only CREATE of DDL is supported in transactions"
    77  }
    78  
    79  func administrativeCommandIsUnsupportedInTxnErrorInfo() string {
    80  	return "administrative command is unsupported in transactions"
    81  }
    82  
    83  func unclassifiedStatementInUncommittedTxnErrorInfo() string {
    84  	return "unclassified statement appears in uncommitted transaction"
    85  }
    86  
    87  func writeWriteConflictsErrorInfo() string {
    88  	return "Write conflicts detected. Previous transaction need to be aborted."
    89  }
    90  
    91  const (
    92  	prefixPrepareStmtName       = "__mo_stmt_id"
    93  	prefixPrepareStmtSessionVar = "__mo_stmt_var"
    94  )
    95  
    96  func getPrepareStmtName(stmtID uint32) string {
    97  	return fmt.Sprintf("%s_%d", prefixPrepareStmtName, stmtID)
    98  }
    99  
   100  func parsePrepareStmtID(s string) uint32 {
   101  	if strings.HasPrefix(s, prefixPrepareStmtName) {
   102  		ss := strings.Split(s, "_")
   103  		v, err := strconv.ParseUint(ss[len(ss)-1], 10, 64)
   104  		if err != nil {
   105  			return 0
   106  		}
   107  		return uint32(v)
   108  	}
   109  	return 0
   110  }
   111  
   112  func GetPrepareStmtID(ctx context.Context, name string) (int, error) {
   113  	idx := len(prefixPrepareStmtName) + 1
   114  	if idx >= len(name) {
   115  		return -1, moerr.NewInternalError(ctx, "can not get Prepare stmtID")
   116  	}
   117  	return strconv.Atoi(name[idx:])
   118  }
   119  
   120  func transferSessionConnType2StatisticConnType(c ConnType) statistic.ConnType {
   121  	switch c {
   122  	case ConnTypeUnset:
   123  		return statistic.ConnTypeUnknown
   124  	case ConnTypeInternal:
   125  		return statistic.ConnTypeInternal
   126  	case ConnTypeExternal:
   127  		return statistic.ConnTypeExternal
   128  	default:
   129  		panic("unknown connection type")
   130  	}
   131  }
   132  
   133  var RecordStatement = func(ctx context.Context, ses *Session, proc *process.Process, cw ComputationWrapper, envBegin time.Time, envStmt, sqlType string, useEnv bool) (context.Context, error) {
   134  	// set StatementID
   135  	var stmID uuid.UUID
   136  	var statement tree.Statement = nil
   137  	var text string
   138  	if cw != nil {
   139  		copy(stmID[:], cw.GetUUID())
   140  		statement = cw.GetAst()
   141  
   142  		ses.ast = statement
   143  
   144  		execSql := makeExecuteSql(ctx, ses, statement)
   145  		if len(execSql) != 0 {
   146  			bb := strings.Builder{}
   147  			bb.WriteString(envStmt)
   148  			bb.WriteString(" // ")
   149  			bb.WriteString(execSql)
   150  			text = SubStringFromBegin(bb.String(), int(getGlobalPu().SV.LengthOfQueryPrinted))
   151  		} else {
   152  			text = SubStringFromBegin(envStmt, int(getGlobalPu().SV.LengthOfQueryPrinted))
   153  		}
   154  	} else {
   155  		stmID, _ = uuid.NewV7()
   156  		text = SubStringFromBegin(envStmt, int(getGlobalPu().SV.LengthOfQueryPrinted))
   157  	}
   158  	ses.SetStmtId(stmID)
   159  	ses.SetStmtType(getStatementType(statement).GetStatementType())
   160  	ses.SetQueryType(getStatementType(statement).GetQueryType())
   161  	ses.SetSqlSourceType(sqlType)
   162  	ses.SetSqlOfStmt(text)
   163  
   164  	//note: txn id here may be empty
   165  	if sqlType != constant.InternalSql {
   166  		ses.pushQueryId(types.Uuid(stmID).ToString())
   167  	}
   168  
   169  	if !motrace.GetTracerProvider().IsEnable() {
   170  		return ctx, nil
   171  	}
   172  	tenant := ses.GetTenantInfo()
   173  	if tenant == nil {
   174  		tenant, _ = GetTenantInfo(ctx, "internal")
   175  	}
   176  	stm := motrace.NewStatementInfo()
   177  	// set TransactionID
   178  	var txn TxnOperator
   179  	var err error
   180  	if handler := ses.GetTxnHandler(); handler.InActiveTxn() {
   181  		txn = handler.GetTxn()
   182  		if err != nil {
   183  			return nil, err
   184  		}
   185  		copy(stm.TransactionID[:], txn.Txn().ID)
   186  	}
   187  	// set SessionID
   188  	copy(stm.SessionID[:], ses.GetUUID())
   189  	requestAt := envBegin
   190  	if !useEnv {
   191  		requestAt = time.Now()
   192  	}
   193  
   194  	copy(stm.StatementID[:], stmID[:])
   195  	// END> set StatementID
   196  	stm.Account = tenant.GetTenant()
   197  	stm.RoleId = proc.SessionInfo.RoleId
   198  	stm.User = tenant.GetUser()
   199  	stm.Host = ses.proto.Peer()
   200  	stm.Database = ses.GetDatabaseName()
   201  	stm.Statement = text
   202  	stm.StatementFingerprint = "" // fixme= (Reserved)
   203  	stm.StatementTag = ""         // fixme= (Reserved)
   204  	stm.SqlSourceType = sqlType
   205  	stm.RequestAt = requestAt
   206  	stm.StatementType = getStatementType(statement).GetStatementType()
   207  	stm.QueryType = getStatementType(statement).GetQueryType()
   208  	stm.ConnType = transferSessionConnType2StatisticConnType(ses.connType)
   209  	if sqlType == constant.InternalSql && isCmdFieldListSql(envStmt) {
   210  		// fix original issue #8165
   211  		stm.User = ""
   212  	}
   213  	if sqlType != constant.InternalSql {
   214  		ses.SetTStmt(stm)
   215  	}
   216  	if !stm.IsZeroTxnID() {
   217  		stm.Report(ctx)
   218  	}
   219  	if stm.IsMoLogger() && stm.StatementType == "Load" && len(stm.Statement) > 128 {
   220  		stm.Statement = envStmt[:40] + "..." + envStmt[len(envStmt)-45:]
   221  	}
   222  
   223  	return motrace.ContextWithStatement(ctx, stm), nil
   224  }
   225  
   226  var RecordParseErrorStatement = func(ctx context.Context, ses *Session, proc *process.Process, envBegin time.Time,
   227  	envStmt []string, sqlTypes []string, err error) (context.Context, error) {
   228  	retErr := moerr.NewParseError(ctx, err.Error())
   229  	/*
   230  		!!!NOTE: the sql may be empty string.
   231  		So, the sqlTypes may be empty slice.
   232  	*/
   233  	sqlType := ""
   234  	if len(sqlTypes) > 0 {
   235  		sqlType = sqlTypes[0]
   236  	} else {
   237  		sqlType = constant.ExternSql
   238  	}
   239  	if len(envStmt) > 0 {
   240  		for i, sql := range envStmt {
   241  			if i < len(sqlTypes) {
   242  				sqlType = sqlTypes[i]
   243  			}
   244  			ctx, err = RecordStatement(ctx, ses, proc, nil, envBegin, sql, sqlType, true)
   245  			if err != nil {
   246  				return nil, err
   247  			}
   248  			motrace.EndStatement(ctx, retErr, 0, 0, 0)
   249  		}
   250  	} else {
   251  		ctx, err = RecordStatement(ctx, ses, proc, nil, envBegin, "", sqlType, true)
   252  		if err != nil {
   253  			return nil, err
   254  		}
   255  		motrace.EndStatement(ctx, retErr, 0, 0, 0)
   256  	}
   257  
   258  	tenant := ses.GetTenantInfo()
   259  	if tenant == nil {
   260  		tenant, _ = GetTenantInfo(ctx, "internal")
   261  	}
   262  	incStatementErrorsCounter(tenant.GetTenant(), nil)
   263  	return ctx, nil
   264  }
   265  
   266  // RecordStatementTxnID record txnID after TxnBegin or Compile(autocommit=1)
   267  var RecordStatementTxnID = func(ctx context.Context, fses FeSession) error {
   268  	var ses *Session
   269  	var ok bool
   270  	if ses, ok = fses.(*Session); !ok {
   271  		return nil
   272  	}
   273  	var txn TxnOperator
   274  	var err error
   275  	if stm := motrace.StatementFromContext(ctx); ses != nil && stm != nil && stm.IsZeroTxnID() {
   276  		if handler := ses.GetTxnHandler(); handler.InActiveTxn() {
   277  			// simplify the logic of TxnOperator. refer to https://github.com/matrixorigin/matrixone/pull/13436#pullrequestreview-1779063200
   278  			txn = handler.GetTxn()
   279  			if err != nil {
   280  				return err
   281  			}
   282  			stm.SetTxnID(txn.Txn().ID)
   283  			ses.SetTxnId(txn.Txn().ID)
   284  		}
   285  		stm.Report(ctx)
   286  	}
   287  
   288  	// set frontend statement's txn-id
   289  	if upSes := ses.upstream; upSes != nil && upSes.tStmt != nil && upSes.tStmt.IsZeroTxnID() /* not record txn-id */ {
   290  		// background session has valid txn
   291  		if handler := ses.GetTxnHandler(); handler.InActiveTxn() {
   292  			txn = handler.GetTxn()
   293  			if err != nil {
   294  				return err
   295  			}
   296  			// set upstream (the frontend session) statement's txn-id
   297  			// PS: only skip ONE txn
   298  			if stmt := upSes.tStmt; stmt.NeedSkipTxn() /* normally set by determineUserHasPrivilegeSet */ {
   299  				// need to skip the whole txn, so it records the skipped txn-id
   300  				stmt.SetSkipTxn(false)
   301  				stmt.SetSkipTxnId(txn.Txn().ID)
   302  			} else if txnId := txn.Txn().ID; !stmt.SkipTxnId(txnId) {
   303  				upSes.tStmt.SetTxnID(txnId)
   304  			}
   305  		}
   306  	}
   307  	return nil
   308  }
   309  
   310  func handleShowTableStatus(ses *Session, execCtx *ExecCtx, stmt *tree.ShowTableStatus) error {
   311  	var db engine.Database
   312  	var err error
   313  
   314  	txnOp := ses.GetTxnHandler().GetTxn()
   315  	ctx := execCtx.reqCtx
   316  	// get db info as current account
   317  	if db, err = ses.GetTxnHandler().GetStorage().Database(ctx, stmt.DbName, txnOp); err != nil {
   318  		return err
   319  	}
   320  
   321  	if db.IsSubscription(ctx) {
   322  		// get global unique (pubAccountName, pubName)
   323  		var pubAccountName, pubName string
   324  		if _, pubAccountName, pubName, err = getSubInfoFromSql(ctx, ses, db.GetCreateSql(ctx)); err != nil {
   325  			return err
   326  		}
   327  
   328  		bh := GetRawBatchBackgroundExec(ctx, ses)
   329  		ctx = context.WithValue(ctx, defines.TenantIDKey{}, uint32(sysAccountID))
   330  		var pubAccountId int32
   331  		if pubAccountId = getAccountIdByName(ctx, ses, bh, pubAccountName); pubAccountId == -1 {
   332  			return moerr.NewInternalError(ctx, "publish account does not exist")
   333  		}
   334  
   335  		// get publication record
   336  		var pubs []*published
   337  		if pubs, err = getPubs(ctx, ses, bh, pubAccountId, pubAccountName, pubName, ses.GetTenantName()); err != nil {
   338  			return err
   339  		}
   340  		if len(pubs) != 1 {
   341  			return moerr.NewInternalError(ctx, "no satisfied publication")
   342  		}
   343  
   344  		// as pub account
   345  		ctx = context.WithValue(ctx, defines.TenantIDKey{}, uint32(pubAccountId))
   346  		// get db as pub account
   347  		if db, err = ses.GetTxnHandler().GetStorage().Database(ctx, pubs[0].pubDatabase, txnOp); err != nil {
   348  			return err
   349  		}
   350  	}
   351  
   352  	getRoleName := func(roleId uint32) (roleName string, err error) {
   353  		sql := getSqlForRoleNameOfRoleId(int64(roleId))
   354  
   355  		var rets []ExecResult
   356  		if rets, err = executeSQLInBackgroundSession(ctx, ses, ses.GetMemPool(), sql); err != nil {
   357  			return "", err
   358  		}
   359  
   360  		if !execResultArrayHasData(rets) {
   361  			return "", moerr.NewInternalError(ctx, "get role name failed")
   362  		}
   363  
   364  		if roleName, err = rets[0].GetString(ctx, 0, 0); err != nil {
   365  			return "", err
   366  		}
   367  		return roleName, nil
   368  	}
   369  
   370  	mrs := ses.GetMysqlResultSet()
   371  	for _, row := range ses.data {
   372  		tableName := string(row[0].([]byte))
   373  		r, err := db.Relation(ctx, tableName, nil)
   374  		if err != nil {
   375  			return err
   376  		}
   377  		if row[3], err = r.Rows(ctx); err != nil {
   378  			return err
   379  		}
   380  		if row[5], err = r.Size(ctx, disttae.AllColumns); err != nil {
   381  			return err
   382  		}
   383  		roleId := row[17].(uint32)
   384  		// role name
   385  		if row[18], err = getRoleName(roleId); err != nil {
   386  			return err
   387  		}
   388  		mrs.AddRow(row)
   389  	}
   390  	return nil
   391  }
   392  
   393  // getDataFromPipeline: extract the data from the pipeline.
   394  // obj: session
   395  func getDataFromPipeline(obj FeSession, execCtx *ExecCtx, bat *batch.Batch) error {
   396  	_, task := gotrace.NewTask(context.TODO(), "frontend.WriteDataToClient")
   397  	defer task.End()
   398  	ses := obj.(*Session)
   399  	if openSaveQueryResult(execCtx.reqCtx, ses) {
   400  		if bat == nil {
   401  			if err := saveQueryResultMeta(execCtx.reqCtx, ses); err != nil {
   402  				return err
   403  			}
   404  		} else {
   405  			if err := saveQueryResult(execCtx.reqCtx, ses, bat); err != nil {
   406  				return err
   407  			}
   408  		}
   409  	}
   410  	if bat == nil {
   411  		return nil
   412  	}
   413  
   414  	begin := time.Now()
   415  	proto := ses.GetMysqlProtocol()
   416  
   417  	ec := ses.GetExportConfig()
   418  	oq := NewOutputQueue(execCtx.reqCtx, ses, len(bat.Vecs), nil, nil)
   419  	row2colTime := time.Duration(0)
   420  	procBatchBegin := time.Now()
   421  	n := bat.Vecs[0].Length()
   422  
   423  	if ec.needExportToFile() {
   424  		initExportFirst(oq)
   425  	}
   426  
   427  	for j := 0; j < n; j++ { //row index
   428  		if ec.needExportToFile() {
   429  			select {
   430  			case <-execCtx.reqCtx.Done():
   431  				return nil
   432  			default:
   433  			}
   434  			continue
   435  		}
   436  
   437  		row, err := extractRowFromEveryVector(execCtx.reqCtx, ses, bat, j, oq, true)
   438  		if err != nil {
   439  			return err
   440  		}
   441  		if oq.showStmtType == ShowTableStatus {
   442  			row2 := make([]interface{}, len(row))
   443  			copy(row2, row)
   444  			ses.AppendData(row2)
   445  		}
   446  	}
   447  
   448  	if ec.needExportToFile() {
   449  		oq.rowIdx = uint64(n)
   450  		bat2 := preCopyBat(obj, bat)
   451  		go constructByte(execCtx.reqCtx, obj, bat2, oq.ep.Index, oq.ep.ByteChan, oq)
   452  	}
   453  	err := oq.flush()
   454  	if err != nil {
   455  		return err
   456  	}
   457  
   458  	procBatchTime := time.Since(procBatchBegin)
   459  	tTime := time.Since(begin)
   460  	ses.sentRows.Add(int64(n))
   461  	logDebugf(ses.GetDebugString(), "rowCount %v \n"+
   462  		"time of getDataFromPipeline : %s \n"+
   463  		"processBatchTime %v \n"+
   464  		"row2colTime %v \n"+
   465  		"restTime(=totalTime - row2colTime) %v \n"+
   466  		"protoStats %s",
   467  		n,
   468  		tTime,
   469  		procBatchTime,
   470  		row2colTime,
   471  		tTime-row2colTime,
   472  		proto.GetStats())
   473  
   474  	return nil
   475  }
   476  
   477  func doUse(ctx context.Context, ses FeSession, db string) error {
   478  	defer RecordStatementTxnID(ctx, ses)
   479  	txnHandler := ses.GetTxnHandler()
   480  	var txn TxnOperator
   481  	var err error
   482  	var dbMeta engine.Database
   483  	txn = txnHandler.GetTxn()
   484  	//TODO: check meta data
   485  	if dbMeta, err = getGlobalPu().StorageEngine.Database(ctx, db, txn); err != nil {
   486  		//echo client. no such database
   487  		return moerr.NewBadDB(ctx, db)
   488  	}
   489  	if dbMeta.IsSubscription(ctx) {
   490  		_, err = checkSubscriptionValid(ctx, ses, dbMeta.GetCreateSql(ctx))
   491  		if err != nil {
   492  			return err
   493  		}
   494  	}
   495  	oldDB := ses.GetDatabaseName()
   496  	ses.SetDatabaseName(db)
   497  
   498  	logDebugf(ses.GetDebugString(), "User %s change database from [%s] to [%s]", ses.GetUserName(), oldDB, ses.GetDatabaseName())
   499  
   500  	return nil
   501  }
   502  
   503  func handleChangeDB(ses FeSession, execCtx *ExecCtx, db string) error {
   504  	return doUse(execCtx.reqCtx, ses, db)
   505  }
   506  
   507  func handleDump(ses FeSession, execCtx *ExecCtx, dump *tree.MoDump) error {
   508  	return doDumpQueryResult(execCtx.reqCtx, ses.(*Session), dump.ExportParams)
   509  }
   510  
   511  func doCmdFieldList(reqCtx context.Context, ses *Session, _ *InternalCmdFieldList) error {
   512  	dbName := ses.GetDatabaseName()
   513  	if dbName == "" {
   514  		return moerr.NewNoDB(reqCtx)
   515  	}
   516  
   517  	//Get table infos for the database from the cube
   518  	//case 1: there are no table infos for the db
   519  	//case 2: db changed
   520  	//NOTE: it costs too much time.
   521  	//It just reduces the information in the auto-completion (auto-rehash) of the mysql client.
   522  	//var attrs []ColumnInfo
   523  	//
   524  	//if tableInfos == nil || db != dbName {
   525  	//	txnHandler := ses.GetTxnHandler()
   526  	//	eng := ses.GetStorage()
   527  	//	db, err := eng.Database(reqCtx, dbName, txnHandler.GetTxn())
   528  	//	if err != nil {
   529  	//		return err
   530  	//	}
   531  	//
   532  	//	names, err := db.Relations(reqCtx)
   533  	//	if err != nil {
   534  	//		return err
   535  	//	}
   536  	//	for _, name := range names {
   537  	//		table, err := db.Relation(reqCtx, name)
   538  	//		if err != nil {
   539  	//			return err
   540  	//		}
   541  	//
   542  	//		defs, err := table.TableDefs(reqCtx)
   543  	//		if err != nil {
   544  	//			return err
   545  	//		}
   546  	//		for _, def := range defs {
   547  	//			if attr, ok := def.(*engine.AttributeDef); ok {
   548  	//				attrs = append(attrs, &engineColumnInfo{
   549  	//					name: attr.Attr.Name,
   550  	//					typ:  attr.Attr.Type,
   551  	//				})
   552  	//			}
   553  	//		}
   554  	//	}
   555  	//
   556  	//	if tableInfos == nil {
   557  	//		tableInfos = make(map[string][]ColumnInfo)
   558  	//	}
   559  	//	tableInfos[tableName] = attrs
   560  	//}
   561  	//
   562  	//cols, ok := tableInfos[tableName]
   563  	//if !ok {
   564  	//	//just give the empty info when there is no such table.
   565  	//	attrs = make([]ColumnInfo, 0)
   566  	//} else {
   567  	//	attrs = cols
   568  	//}
   569  	//
   570  	//for _, c := range attrs {
   571  	//	col := new(MysqlColumn)
   572  	//	col.SetName(c.GetName())
   573  	//	err = convertEngineTypeToMysqlType(c.GetType(), col)
   574  	//	if err != nil {
   575  	//		return err
   576  	//	}
   577  	//
   578  	//	/*
   579  	//		mysql CMD_FIELD_LIST response: send the column definition per column
   580  	//	*/
   581  	//	err = proto.SendColumnDefinitionPacket(col, int(COM_FIELD_LIST))
   582  	//	if err != nil {
   583  	//		return err
   584  	//	}
   585  	//}
   586  	return nil
   587  }
   588  
   589  /*
   590  handle cmd CMD_FIELD_LIST
   591  */
   592  func handleCmdFieldList(ses FeSession, execCtx *ExecCtx, icfl *InternalCmdFieldList) error {
   593  	var err error
   594  	proto := ses.GetMysqlProtocol()
   595  
   596  	ses.SetMysqlResultSet(nil)
   597  	err = doCmdFieldList(execCtx.reqCtx, ses.(*Session), icfl)
   598  	if err != nil {
   599  		return err
   600  	}
   601  
   602  	/*
   603  		mysql CMD_FIELD_LIST response: End after the column has been sent.
   604  		send EOF packet
   605  	*/
   606  	err = proto.sendEOFOrOkPacket(0, ses.GetTxnHandler().GetServerStatus())
   607  	if err != nil {
   608  		return err
   609  	}
   610  
   611  	return err
   612  }
   613  
   614  func doSetVar(ses *Session, execCtx *ExecCtx, sv *tree.SetVar, sql string) error {
   615  	var err error = nil
   616  	var ok bool
   617  	setVarFunc := func(system, global bool, name string, value interface{}, sql string) error {
   618  		var oldValueRaw interface{}
   619  		if system {
   620  			if global {
   621  				err = doCheckRole(execCtx.reqCtx, ses)
   622  				if err != nil {
   623  					return err
   624  				}
   625  				err = ses.SetGlobalVar(execCtx.reqCtx, name, value)
   626  				if err != nil {
   627  					return err
   628  				}
   629  				err = doSetGlobalSystemVariable(execCtx.reqCtx, ses, name, value)
   630  				if err != nil {
   631  					return err
   632  				}
   633  			} else {
   634  				if strings.ToLower(name) == "autocommit" {
   635  					oldValueRaw, err = ses.GetSessionVar(execCtx.reqCtx, "autocommit")
   636  					if err != nil {
   637  						return err
   638  					}
   639  				}
   640  				err = ses.SetSessionVar(execCtx.reqCtx, name, value)
   641  				if err != nil {
   642  					return err
   643  				}
   644  			}
   645  
   646  			if strings.ToLower(name) == "autocommit" {
   647  				oldValue, err := valueIsBoolTrue(oldValueRaw)
   648  				if err != nil {
   649  					return err
   650  				}
   651  				newValue, err := valueIsBoolTrue(value)
   652  				if err != nil {
   653  					return err
   654  				}
   655  				err = ses.GetTxnHandler().SetAutocommit(execCtx, oldValue, newValue)
   656  				if err != nil {
   657  					return err
   658  				}
   659  			}
   660  		} else {
   661  			err = ses.SetUserDefinedVar(name, value, sql)
   662  			if err != nil {
   663  				return err
   664  			}
   665  		}
   666  		return nil
   667  	}
   668  	for _, assign := range sv.Assignments {
   669  		name := assign.Name
   670  		var value interface{}
   671  
   672  		value, err = getExprValue(assign.Value, ses, execCtx)
   673  		if err != nil {
   674  			return err
   675  		}
   676  
   677  		if systemVar, ok := gSysVarsDefs[name]; ok {
   678  			if isDefault, ok := value.(bool); ok && isDefault {
   679  				value = systemVar.Default
   680  			}
   681  		}
   682  
   683  		//TODO : fix SET NAMES after parser is ready
   684  		if name == "names" {
   685  			//replaced into three system variable:
   686  			//character_set_client, character_set_connection, and character_set_results
   687  			replacedBy := []string{
   688  				"character_set_client", "character_set_connection", "character_set_results",
   689  			}
   690  			for _, rb := range replacedBy {
   691  				err = setVarFunc(assign.System, assign.Global, rb, value, sql)
   692  				if err != nil {
   693  					return err
   694  				}
   695  			}
   696  		} else if name == "syspublications" {
   697  			if !ses.GetTenantInfo().IsSysTenant() {
   698  				return moerr.NewInternalError(execCtx.reqCtx, "only system account can set system variable syspublications")
   699  			}
   700  			err = setVarFunc(assign.System, assign.Global, name, value, sql)
   701  			if err != nil {
   702  				return err
   703  			}
   704  		} else if name == "clear_privilege_cache" {
   705  			//if it is global variable, it does nothing.
   706  			if !assign.Global {
   707  				//if the value is 'on or off', just invalidate the privilege cache
   708  				ok, err = valueIsBoolTrue(value)
   709  				if err != nil {
   710  					return err
   711  				}
   712  
   713  				if ok {
   714  					cache := ses.GetPrivilegeCache()
   715  					if cache != nil {
   716  						cache.invalidate()
   717  					}
   718  				}
   719  				err = setVarFunc(assign.System, assign.Global, name, value, sql)
   720  				if err != nil {
   721  					return err
   722  				}
   723  			}
   724  		} else if name == "enable_privilege_cache" {
   725  			ok, err = valueIsBoolTrue(value)
   726  			if err != nil {
   727  				return err
   728  			}
   729  
   730  			//disable privilege cache. clean the cache.
   731  			if !ok {
   732  				cache := ses.GetPrivilegeCache()
   733  				if cache != nil {
   734  					cache.invalidate()
   735  				}
   736  			}
   737  			err = setVarFunc(assign.System, assign.Global, name, value, sql)
   738  			if err != nil {
   739  				return err
   740  			}
   741  		} else if name == "optimizer_hints" {
   742  			err = setVarFunc(assign.System, assign.Global, name, value, sql)
   743  			if err != nil {
   744  				return err
   745  			}
   746  			runtime.ProcessLevelRuntime().SetGlobalVariables("optimizer_hints", value)
   747  		} else if name == "runtime_filter_limit_in" {
   748  			err = setVarFunc(assign.System, assign.Global, name, value, sql)
   749  			if err != nil {
   750  				return err
   751  			}
   752  			runtime.ProcessLevelRuntime().SetGlobalVariables("runtime_filter_limit_in", value)
   753  		} else if name == "runtime_filter_limit_bloom_filter" {
   754  			err = setVarFunc(assign.System, assign.Global, name, value, sql)
   755  			if err != nil {
   756  				return err
   757  			}
   758  			runtime.ProcessLevelRuntime().SetGlobalVariables("runtime_filter_limit_bloom_filter", value)
   759  		} else {
   760  			err = setVarFunc(assign.System, assign.Global, name, value, sql)
   761  			if err != nil {
   762  				return err
   763  			}
   764  		}
   765  	}
   766  	return err
   767  }
   768  
   769  /*
   770  handle setvar
   771  */
   772  func handleSetVar(ses FeSession, execCtx *ExecCtx, sv *tree.SetVar, sql string) error {
   773  	err := doSetVar(ses.(*Session), execCtx, sv, sql)
   774  	if err != nil {
   775  		return err
   776  	}
   777  
   778  	return nil
   779  }
   780  
   781  func doShowErrors(ses *Session) error {
   782  	var err error
   783  
   784  	levelCol := new(MysqlColumn)
   785  	levelCol.SetColumnType(defines.MYSQL_TYPE_VARCHAR)
   786  	levelCol.SetName("Level")
   787  
   788  	CodeCol := new(MysqlColumn)
   789  	CodeCol.SetColumnType(defines.MYSQL_TYPE_SHORT)
   790  	CodeCol.SetName("Code")
   791  
   792  	MsgCol := new(MysqlColumn)
   793  	MsgCol.SetColumnType(defines.MYSQL_TYPE_VARCHAR)
   794  	MsgCol.SetName("Message")
   795  
   796  	mrs := ses.GetMysqlResultSet()
   797  
   798  	mrs.AddColumn(levelCol)
   799  	mrs.AddColumn(CodeCol)
   800  	mrs.AddColumn(MsgCol)
   801  
   802  	info := ses.GetErrInfo()
   803  
   804  	for i := info.length() - 1; i >= 0; i-- {
   805  		row := make([]interface{}, 3)
   806  		row[0] = "Error"
   807  		row[1] = info.codes[i]
   808  		row[2] = info.msgs[i]
   809  		mrs.AddRow(row)
   810  	}
   811  
   812  	return err
   813  }
   814  
   815  func handleShowErrors(ses FeSession) error {
   816  	err := doShowErrors(ses.(*Session))
   817  	if err != nil {
   818  		return err
   819  	}
   820  	return err
   821  }
   822  
   823  func doShowVariables(ses *Session, execCtx *ExecCtx, sv *tree.ShowVariables) error {
   824  	if sv.Like != nil && sv.Where != nil {
   825  		return moerr.NewSyntaxError(execCtx.reqCtx, "like clause and where clause cannot exist at the same time")
   826  	}
   827  
   828  	var err error = nil
   829  
   830  	col1 := new(MysqlColumn)
   831  	col1.SetColumnType(defines.MYSQL_TYPE_VARCHAR)
   832  	col1.SetName("Variable_name")
   833  
   834  	col2 := new(MysqlColumn)
   835  	col2.SetColumnType(defines.MYSQL_TYPE_VARCHAR)
   836  	col2.SetName("Value")
   837  
   838  	mrs := ses.GetMysqlResultSet()
   839  	mrs.AddColumn(col1)
   840  	mrs.AddColumn(col2)
   841  
   842  	var hasLike = false
   843  	var likePattern = ""
   844  	var isIlike = false
   845  	if sv.Like != nil {
   846  		hasLike = true
   847  		if sv.Like.Op == tree.ILIKE {
   848  			isIlike = true
   849  		}
   850  		likePattern = strings.ToLower(sv.Like.Right.String())
   851  	}
   852  
   853  	var sysVars map[string]interface{}
   854  	if sv.Global {
   855  		sysVars, err = doGetGlobalSystemVariable(execCtx.reqCtx, ses)
   856  		if err != nil {
   857  			return err
   858  		}
   859  	} else {
   860  		sysVars = ses.CopyAllSessionVars()
   861  	}
   862  
   863  	rows := make([][]interface{}, 0, len(sysVars))
   864  	for name, value := range sysVars {
   865  		if hasLike {
   866  			s := name
   867  			if isIlike {
   868  				s = strings.ToLower(s)
   869  			}
   870  			if !WildcardMatch(likePattern, s) {
   871  				continue
   872  			}
   873  		}
   874  		row := make([]interface{}, 2)
   875  		row[0] = name
   876  		gsv, ok := GSysVariables.GetDefinitionOfSysVar(name)
   877  		if !ok {
   878  			return moerr.NewInternalError(execCtx.reqCtx, errorSystemVariableDoesNotExist())
   879  		}
   880  		row[1] = value
   881  		if svbt, ok2 := gsv.GetType().(SystemVariableBoolType); ok2 {
   882  			if svbt.IsTrue(value) {
   883  				row[1] = "on"
   884  			} else {
   885  				row[1] = "off"
   886  			}
   887  		}
   888  		rows = append(rows, row)
   889  	}
   890  
   891  	if sv.Where != nil {
   892  		bat, err := constructVarBatch(ses, rows)
   893  		if err != nil {
   894  			return err
   895  		}
   896  		binder := plan2.NewDefaultBinder(execCtx.reqCtx, nil, nil, plan2.Type{Id: int32(types.T_varchar), Width: types.MaxVarcharLen}, []string{"variable_name", "value"})
   897  		planExpr, err := binder.BindExpr(sv.Where.Expr, 0, false)
   898  		if err != nil {
   899  			return err
   900  		}
   901  
   902  		executor, err := colexec.NewExpressionExecutor(execCtx.proc, planExpr)
   903  		if err != nil {
   904  			return err
   905  		}
   906  		vec, err := executor.Eval(execCtx.proc, []*batch.Batch{bat})
   907  		if err != nil {
   908  			executor.Free()
   909  			return err
   910  		}
   911  
   912  		bs := vector.MustFixedCol[bool](vec)
   913  		sels := execCtx.proc.Mp().GetSels()
   914  		for i, b := range bs {
   915  			if b {
   916  				sels = append(sels, int64(i))
   917  			}
   918  		}
   919  		executor.Free()
   920  
   921  		bat.Shrink(sels, false)
   922  		execCtx.proc.Mp().PutSels(sels)
   923  		v0 := vector.MustStrCol(bat.Vecs[0])
   924  		v1 := vector.MustStrCol(bat.Vecs[1])
   925  		rows = rows[:len(v0)]
   926  		for i := range v0 {
   927  			rows[i][0] = v0[i]
   928  			rows[i][1] = v1[i]
   929  		}
   930  		bat.Clean(execCtx.proc.Mp())
   931  	}
   932  
   933  	//sort by name
   934  	sort.Slice(rows, func(i, j int) bool {
   935  		return rows[i][0].(string) < rows[j][0].(string)
   936  	})
   937  
   938  	for _, row := range rows {
   939  		mrs.AddRow(row)
   940  	}
   941  
   942  	return err
   943  }
   944  
   945  /*
   946  handle show variables
   947  */
   948  func handleShowVariables(ses FeSession, execCtx *ExecCtx, sv *tree.ShowVariables) error {
   949  	err := doShowVariables(ses.(*Session), execCtx, sv)
   950  	if err != nil {
   951  		return err
   952  	}
   953  	return err
   954  }
   955  
   956  func constructVarBatch(ses *Session, rows [][]interface{}) (*batch.Batch, error) {
   957  	bat := batch.New(true, []string{"Variable_name", "Value"})
   958  	typ := types.New(types.T_varchar, types.MaxVarcharLen, 0)
   959  	cnt := len(rows)
   960  	bat.SetRowCount(cnt)
   961  	v0 := make([]string, cnt)
   962  	v1 := make([]string, cnt)
   963  	for i, row := range rows {
   964  		v0[i] = row[0].(string)
   965  		v1[i] = fmt.Sprintf("%v", row[1])
   966  	}
   967  	bat.Vecs[0] = vector.NewVec(typ)
   968  	vector.AppendStringList(bat.Vecs[0], v0, nil, ses.GetMemPool())
   969  	bat.Vecs[1] = vector.NewVec(typ)
   970  	vector.AppendStringList(bat.Vecs[1], v1, nil, ses.GetMemPool())
   971  	return bat, nil
   972  }
   973  
   974  func constructCollationBatch(ses *Session, rows [][]interface{}) (*batch.Batch, error) {
   975  	bat := batch.New(true, []string{"Collation", "Charset", "Id", "Default", "Compiled", "Sortlen", "Pad_attribute"})
   976  	typ := types.New(types.T_varchar, types.MaxVarcharLen, 0)
   977  	longlongTyp := types.New(types.T_int64, 0, 0)
   978  	longTyp := types.New(types.T_int32, 0, 0)
   979  	cnt := len(rows)
   980  	bat.SetRowCount(cnt)
   981  	v0 := make([]string, cnt)
   982  	v1 := make([]string, cnt)
   983  	v2 := make([]int64, cnt)
   984  	v3 := make([]string, cnt)
   985  	v4 := make([]string, cnt)
   986  	v5 := make([]int32, cnt)
   987  	v6 := make([]string, cnt)
   988  	for i, row := range rows {
   989  		v0[i] = row[0].(string)
   990  		v1[i] = row[1].(string)
   991  		v2[i] = row[2].(int64)
   992  		v3[i] = row[3].(string)
   993  		v4[i] = row[4].(string)
   994  		v5[i] = row[5].(int32)
   995  		v6[i] = row[6].(string)
   996  	}
   997  	bat.Vecs[0] = vector.NewVec(typ)
   998  	vector.AppendStringList(bat.Vecs[0], v0, nil, ses.GetMemPool())
   999  	bat.Vecs[1] = vector.NewVec(typ)
  1000  	vector.AppendStringList(bat.Vecs[1], v1, nil, ses.GetMemPool())
  1001  	bat.Vecs[2] = vector.NewVec(longlongTyp)
  1002  	vector.AppendFixedList[int64](bat.Vecs[2], v2, nil, ses.GetMemPool())
  1003  	bat.Vecs[3] = vector.NewVec(typ)
  1004  	vector.AppendStringList(bat.Vecs[3], v3, nil, ses.GetMemPool())
  1005  	bat.Vecs[4] = vector.NewVec(typ)
  1006  	vector.AppendStringList(bat.Vecs[4], v4, nil, ses.GetMemPool())
  1007  	bat.Vecs[5] = vector.NewVec(longTyp)
  1008  	vector.AppendFixedList[int32](bat.Vecs[5], v5, nil, ses.GetMemPool())
  1009  	bat.Vecs[6] = vector.NewVec(typ)
  1010  	vector.AppendStringList(bat.Vecs[6], v6, nil, ses.GetMemPool())
  1011  	return bat, nil
  1012  }
  1013  
  1014  func handleAnalyzeStmt(ses *Session, execCtx *ExecCtx, stmt *tree.AnalyzeStmt) error {
  1015  	// rewrite analyzeStmt to `select approx_count_distinct(col), .. from tbl`
  1016  	// IMO, this approach is simple and future-proof
  1017  	// Although this rewriting processing could have been handled in rewrite module,
  1018  	// `handleAnalyzeStmt` can be easily managed by cron jobs in the future
  1019  	ctx := tree.NewFmtCtx(dialect.MYSQL)
  1020  	ctx.WriteString("select ")
  1021  	for i, ident := range stmt.Cols {
  1022  		if i > 0 {
  1023  			ctx.WriteByte(',')
  1024  		}
  1025  		ctx.WriteString("approx_count_distinct(")
  1026  		ctx.WriteString(string(ident))
  1027  		ctx.WriteByte(')')
  1028  	}
  1029  	ctx.WriteString(" from ")
  1030  	stmt.Table.Format(ctx)
  1031  	sql := ctx.String()
  1032  	//backup the inside statement
  1033  	prevInsideStmt := ses.ReplaceDerivedStmt(true)
  1034  	defer func() {
  1035  		//restore the inside statement
  1036  		ses.ReplaceDerivedStmt(prevInsideStmt)
  1037  	}()
  1038  	tempExecCtx := ExecCtx{
  1039  		ses:    ses,
  1040  		reqCtx: execCtx.reqCtx,
  1041  	}
  1042  	return doComQuery(ses, &tempExecCtx, &UserInput{sql: sql})
  1043  }
  1044  
  1045  func doExplainStmt(reqCtx context.Context, ses *Session, stmt *tree.ExplainStmt) error {
  1046  
  1047  	//1. generate the plan
  1048  	es, err := getExplainOption(reqCtx, stmt.Options)
  1049  	if err != nil {
  1050  		return err
  1051  	}
  1052  
  1053  	//get query optimizer and execute Optimize
  1054  	exPlan, err := buildPlan(reqCtx, ses, ses.GetTxnCompileCtx(), stmt.Statement)
  1055  	if err != nil {
  1056  		return err
  1057  	}
  1058  	if exPlan.GetDcl() != nil && exPlan.GetDcl().GetExecute() != nil {
  1059  		//replace the plan of the EXECUTE by the plan generated by the PREPARE
  1060  		execPlan := exPlan.GetDcl().GetExecute()
  1061  		replaced, _, err := ses.GetTxnCompileCtx().ReplacePlan(execPlan)
  1062  		if err != nil {
  1063  			return err
  1064  		}
  1065  
  1066  		exPlan = replaced
  1067  		paramVals := ses.GetTxnCompileCtx().tcw.paramVals
  1068  		if len(paramVals) > 0 {
  1069  			//replace the param var in the plan by the param value
  1070  			exPlan, err = plan2.FillValuesOfParamsInPlan(reqCtx, exPlan, paramVals)
  1071  			if err != nil {
  1072  				return err
  1073  			}
  1074  			if exPlan == nil {
  1075  				return moerr.NewInternalError(reqCtx, "failed to copy exPlan")
  1076  			}
  1077  		}
  1078  	}
  1079  	if exPlan.GetQuery() == nil {
  1080  		return moerr.NewNotSupported(reqCtx, "the sql query plan does not support explain.")
  1081  	}
  1082  	// generator query explain
  1083  	explainQuery := explain.NewExplainQueryImpl(exPlan.GetQuery())
  1084  
  1085  	// build explain data buffer
  1086  	buffer := explain.NewExplainDataBuffer()
  1087  	err = explainQuery.ExplainPlan(reqCtx, buffer, es)
  1088  	if err != nil {
  1089  		return err
  1090  	}
  1091  
  1092  	//2. fill the result set
  1093  	explainColName := "QUERY PLAN"
  1094  	//column
  1095  	col1 := new(MysqlColumn)
  1096  	col1.SetColumnType(defines.MYSQL_TYPE_VAR_STRING)
  1097  	col1.SetName(explainColName)
  1098  
  1099  	mrs := ses.GetMysqlResultSet()
  1100  	mrs.AddColumn(col1)
  1101  
  1102  	for _, line := range buffer.Lines {
  1103  		mrs.AddRow([]any{line})
  1104  	}
  1105  	ses.rs = mysqlColDef2PlanResultColDef(mrs)
  1106  
  1107  	if openSaveQueryResult(reqCtx, ses) {
  1108  		//3. fill the batch for saving the query result
  1109  		bat, err := fillQueryBatch(ses, explainColName, buffer.Lines)
  1110  		defer bat.Clean(ses.GetMemPool())
  1111  		if err != nil {
  1112  			return err
  1113  		}
  1114  
  1115  		// save query result
  1116  		err = maySaveQueryResult(reqCtx, ses, bat)
  1117  		if err != nil {
  1118  
  1119  			return err
  1120  		}
  1121  	}
  1122  	return nil
  1123  }
  1124  
  1125  func fillQueryBatch(ses *Session, explainColName string, lines []string) (*batch.Batch, error) {
  1126  	bat := batch.New(true, []string{explainColName})
  1127  	typ := types.New(types.T_varchar, types.MaxVarcharLen, 0)
  1128  
  1129  	cnt := len(lines)
  1130  	bat.SetRowCount(cnt)
  1131  	bat.Vecs[0] = vector.NewVec(typ)
  1132  	err := vector.AppendStringList(bat.Vecs[0], lines, nil, ses.GetMemPool())
  1133  	if err != nil {
  1134  		return nil, err
  1135  	}
  1136  	return bat, nil
  1137  }
  1138  
  1139  // Note: for pass the compile quickly. We will remove the comments in the future.
  1140  func handleExplainStmt(ses FeSession, execCtx *ExecCtx, stmt *tree.ExplainStmt) error {
  1141  	return doExplainStmt(execCtx.reqCtx, ses.(*Session), stmt)
  1142  }
  1143  
  1144  func doPrepareStmt(ctx context.Context, ses *Session, st *tree.PrepareStmt, sql string, paramTypes []byte) (*PrepareStmt, error) {
  1145  	preparePlan, err := buildPlan(ctx, ses, ses.GetTxnCompileCtx(), st)
  1146  	if err != nil {
  1147  		return nil, err
  1148  	}
  1149  
  1150  	prepareStmt := &PrepareStmt{
  1151  		Name:                preparePlan.GetDcl().GetPrepare().GetName(),
  1152  		Sql:                 sql,
  1153  		PreparePlan:         preparePlan,
  1154  		PrepareStmt:         st.Stmt,
  1155  		getFromSendLongData: make(map[int]struct{}),
  1156  	}
  1157  	if len(paramTypes) > 0 {
  1158  		prepareStmt.ParamTypes = paramTypes
  1159  	}
  1160  	prepareStmt.InsertBat = ses.GetTxnCompileCtx().GetProcess().GetPrepareBatch()
  1161  	err = ses.SetPrepareStmt(ctx, preparePlan.GetDcl().GetPrepare().GetName(), prepareStmt)
  1162  
  1163  	return prepareStmt, err
  1164  }
  1165  
  1166  // handlePrepareStmt
  1167  func handlePrepareStmt(ses FeSession, execCtx *ExecCtx, st *tree.PrepareStmt) (*PrepareStmt, error) {
  1168  	return doPrepareStmt(execCtx.reqCtx, ses.(*Session), st, execCtx.sqlOfStmt, execCtx.executeParamTypes)
  1169  }
  1170  
  1171  func doPrepareString(ses *Session, execCtx *ExecCtx, st *tree.PrepareString) (*PrepareStmt, error) {
  1172  	v, err := ses.GetGlobalVar(execCtx.reqCtx, "lower_case_table_names")
  1173  	if err != nil {
  1174  		return nil, err
  1175  	}
  1176  
  1177  	origin, err := ses.GetGlobalVar(execCtx.reqCtx, "keep_user_target_list_in_result")
  1178  	if err != nil {
  1179  		return nil, err
  1180  	}
  1181  
  1182  	stmts, err := mysql.Parse(execCtx.reqCtx, st.Sql, v.(int64), origin.(int64))
  1183  	if err != nil {
  1184  		return nil, err
  1185  	}
  1186  
  1187  	preparePlan, err := buildPlan(execCtx.reqCtx, ses, ses.GetTxnCompileCtx(), st)
  1188  	if err != nil {
  1189  		return nil, err
  1190  	}
  1191  	prepareStmt := &PrepareStmt{
  1192  		Name:        preparePlan.GetDcl().GetPrepare().GetName(),
  1193  		Sql:         st.Sql,
  1194  		PreparePlan: preparePlan,
  1195  		PrepareStmt: stmts[0],
  1196  	}
  1197  	prepareStmt.InsertBat = ses.GetTxnCompileCtx().GetProcess().GetPrepareBatch()
  1198  	err = ses.SetPrepareStmt(execCtx.reqCtx, preparePlan.GetDcl().GetPrepare().GetName(), prepareStmt)
  1199  	return prepareStmt, err
  1200  }
  1201  
  1202  // handlePrepareString
  1203  func handlePrepareString(ses FeSession, execCtx *ExecCtx, st *tree.PrepareString) (*PrepareStmt, error) {
  1204  	return doPrepareString(ses.(*Session), execCtx, st)
  1205  }
  1206  
  1207  func doDeallocate(ses *Session, execCtx *ExecCtx, st *tree.Deallocate) error {
  1208  	deallocatePlan, err := buildPlan(execCtx.reqCtx, ses, ses.GetTxnCompileCtx(), st)
  1209  	if err != nil {
  1210  		return err
  1211  	}
  1212  	ses.RemovePrepareStmt(deallocatePlan.GetDcl().GetDeallocate().GetName())
  1213  	return nil
  1214  }
  1215  
  1216  func doReset(_ context.Context, _ *Session, _ *tree.Reset) error {
  1217  	return nil
  1218  }
  1219  
  1220  // handleDeallocate
  1221  func handleDeallocate(ses FeSession, execCtx *ExecCtx, st *tree.Deallocate) error {
  1222  	return doDeallocate(ses.(*Session), execCtx, st)
  1223  }
  1224  
  1225  // handleReset
  1226  func handleReset(ses FeSession, execCtx *ExecCtx, st *tree.Reset) error {
  1227  	return doReset(execCtx.reqCtx, ses.(*Session), st)
  1228  }
  1229  
  1230  func handleCreatePublication(ses FeSession, execCtx *ExecCtx, cp *tree.CreatePublication) error {
  1231  	return doCreatePublication(execCtx.reqCtx, ses.(*Session), cp)
  1232  }
  1233  
  1234  func handleAlterPublication(ses FeSession, execCtx *ExecCtx, ap *tree.AlterPublication) error {
  1235  	return doAlterPublication(execCtx.reqCtx, ses.(*Session), ap)
  1236  }
  1237  
  1238  func handleDropPublication(ses FeSession, execCtx *ExecCtx, dp *tree.DropPublication) error {
  1239  	return doDropPublication(execCtx.reqCtx, ses.(*Session), dp)
  1240  }
  1241  
  1242  func handleCreateStage(ses FeSession, execCtx *ExecCtx, cs *tree.CreateStage) error {
  1243  	return doCreateStage(execCtx.reqCtx, ses.(*Session), cs)
  1244  }
  1245  
  1246  func handleAlterStage(ses FeSession, execCtx *ExecCtx, as *tree.AlterStage) error {
  1247  	return doAlterStage(execCtx.reqCtx, ses.(*Session), as)
  1248  }
  1249  
  1250  func handleDropStage(ses FeSession, execCtx *ExecCtx, ds *tree.DropStage) error {
  1251  	return doDropStage(execCtx.reqCtx, ses.(*Session), ds)
  1252  }
  1253  
  1254  func handleCreateSnapshot(ses *Session, execCtx *ExecCtx, ct *tree.CreateSnapShot) error {
  1255  	return doCreateSnapshot(execCtx.reqCtx, ses, ct)
  1256  }
  1257  
  1258  func handleDropSnapshot(ses *Session, execCtx *ExecCtx, ct *tree.DropSnapShot) error {
  1259  	return doDropSnapshot(execCtx.reqCtx, ses, ct)
  1260  }
  1261  
  1262  func handleRestoreSnapshot(ses *Session, execCtx *ExecCtx, rs *tree.RestoreSnapShot) error {
  1263  	return doRestoreSnapshot(execCtx.reqCtx, ses, rs)
  1264  }
  1265  
  1266  // handleCreateAccount creates a new user-level tenant in the context of the tenant SYS
  1267  // which has been initialized.
  1268  func handleCreateAccount(ses FeSession, execCtx *ExecCtx, ca *tree.CreateAccount, proc *process.Process) error {
  1269  	//step1 : create new account.
  1270  	create := &createAccount{
  1271  		IfNotExists:  ca.IfNotExists,
  1272  		IdentTyp:     ca.AuthOption.IdentifiedType.Typ,
  1273  		StatusOption: ca.StatusOption,
  1274  		Comment:      ca.Comment,
  1275  	}
  1276  
  1277  	b := strParamBinder{
  1278  		ctx:    execCtx.reqCtx,
  1279  		params: proc.GetPrepareParams(),
  1280  	}
  1281  	create.Name = b.bind(ca.Name)
  1282  	create.AdminName = b.bind(ca.AuthOption.AdminName)
  1283  	create.IdentStr = b.bindIdentStr(&ca.AuthOption.IdentifiedType)
  1284  	if b.err != nil {
  1285  		return b.err
  1286  	}
  1287  
  1288  	return InitGeneralTenant(execCtx.reqCtx, ses.(*Session), create)
  1289  }
  1290  
  1291  func handleDropAccount(ses FeSession, execCtx *ExecCtx, da *tree.DropAccount, proc *process.Process) error {
  1292  	drop := &dropAccount{
  1293  		IfExists: da.IfExists,
  1294  	}
  1295  
  1296  	b := strParamBinder{
  1297  		ctx:    execCtx.reqCtx,
  1298  		params: proc.GetPrepareParams(),
  1299  	}
  1300  	drop.Name = b.bind(da.Name)
  1301  	if b.err != nil {
  1302  		return b.err
  1303  	}
  1304  
  1305  	return doDropAccount(execCtx.reqCtx, ses.(*Session), drop)
  1306  }
  1307  
  1308  // handleDropAccount drops a new user-level tenant
  1309  func handleAlterAccount(ses FeSession, execCtx *ExecCtx, st *tree.AlterAccount, proc *process.Process) error {
  1310  	aa := &alterAccount{
  1311  		IfExists:     st.IfExists,
  1312  		StatusOption: st.StatusOption,
  1313  		Comment:      st.Comment,
  1314  	}
  1315  
  1316  	b := strParamBinder{
  1317  		ctx:    execCtx.reqCtx,
  1318  		params: proc.GetPrepareParams(),
  1319  	}
  1320  
  1321  	aa.Name = b.bind(st.Name)
  1322  	if st.AuthOption.Exist {
  1323  		aa.AuthExist = true
  1324  		aa.AdminName = b.bind(st.AuthOption.AdminName)
  1325  		aa.IdentTyp = st.AuthOption.IdentifiedType.Typ
  1326  		aa.IdentStr = b.bindIdentStr(&st.AuthOption.IdentifiedType)
  1327  	}
  1328  	if b.err != nil {
  1329  		return b.err
  1330  	}
  1331  
  1332  	return doAlterAccount(execCtx.reqCtx, ses.(*Session), aa)
  1333  }
  1334  
  1335  // handleAlterDatabaseConfig alter a database's mysql_compatibility_mode
  1336  func handleAlterDataBaseConfig(ses FeSession, execCtx *ExecCtx, ad *tree.AlterDataBaseConfig) error {
  1337  	return doAlterDatabaseConfig(execCtx.reqCtx, ses.(*Session), ad)
  1338  }
  1339  
  1340  // handleAlterAccountConfig alter a account's mysql_compatibility_mode
  1341  func handleAlterAccountConfig(ses FeSession, execCtx *ExecCtx, st *tree.AlterDataBaseConfig) error {
  1342  	return doAlterAccountConfig(execCtx.reqCtx, ses.(*Session), st)
  1343  }
  1344  
  1345  // handleCreateUser creates the user for the tenant
  1346  func handleCreateUser(ses FeSession, execCtx *ExecCtx, st *tree.CreateUser) error {
  1347  	tenant := ses.GetTenantInfo()
  1348  
  1349  	cu := &createUser{
  1350  		IfNotExists:        st.IfNotExists,
  1351  		Role:               st.Role,
  1352  		Users:              make([]*user, 0, len(st.Users)),
  1353  		MiscOpt:            st.MiscOpt,
  1354  		CommentOrAttribute: st.CommentOrAttribute,
  1355  	}
  1356  
  1357  	for _, u := range st.Users {
  1358  		v := user{
  1359  			Username: u.Username,
  1360  			Hostname: u.Hostname,
  1361  		}
  1362  		if u.AuthOption != nil {
  1363  			v.AuthExist = true
  1364  			v.IdentTyp = u.AuthOption.Typ
  1365  			switch v.IdentTyp {
  1366  			case tree.AccountIdentifiedByPassword,
  1367  				tree.AccountIdentifiedWithSSL:
  1368  				var err error
  1369  				v.IdentStr, err = unboxExprStr(execCtx.reqCtx, u.AuthOption.Str)
  1370  				if err != nil {
  1371  					return err
  1372  				}
  1373  			}
  1374  		}
  1375  		cu.Users = append(cu.Users, &v)
  1376  	}
  1377  
  1378  	//step1 : create the user
  1379  	return InitUser(execCtx.reqCtx, ses.(*Session), tenant, cu)
  1380  }
  1381  
  1382  // handleDropUser drops the user for the tenant
  1383  func handleDropUser(ses FeSession, execCtx *ExecCtx, du *tree.DropUser) error {
  1384  	return doDropUser(execCtx.reqCtx, ses.(*Session), du)
  1385  }
  1386  
  1387  func handleAlterUser(ses FeSession, execCtx *ExecCtx, st *tree.AlterUser) error {
  1388  	au := &alterUser{
  1389  		IfExists: st.IfExists,
  1390  		Users:    make([]*user, 0, len(st.Users)),
  1391  		Role:     st.Role,
  1392  		MiscOpt:  st.MiscOpt,
  1393  
  1394  		CommentOrAttribute: st.CommentOrAttribute,
  1395  	}
  1396  
  1397  	for _, su := range st.Users {
  1398  		u := &user{
  1399  			Username: su.Username,
  1400  			Hostname: su.Hostname,
  1401  		}
  1402  		if su.AuthOption != nil {
  1403  			u.AuthExist = true
  1404  			u.IdentTyp = su.AuthOption.Typ
  1405  			switch u.IdentTyp {
  1406  			case tree.AccountIdentifiedByPassword,
  1407  				tree.AccountIdentifiedWithSSL:
  1408  				var err error
  1409  				u.IdentStr, err = unboxExprStr(execCtx.reqCtx, su.AuthOption.Str)
  1410  				if err != nil {
  1411  					return err
  1412  				}
  1413  			}
  1414  		}
  1415  		au.Users = append(au.Users, u)
  1416  	}
  1417  	return doAlterUser(execCtx.reqCtx, ses.(*Session), au)
  1418  }
  1419  
  1420  // handleCreateRole creates the new role
  1421  func handleCreateRole(ses FeSession, execCtx *ExecCtx, cr *tree.CreateRole) error {
  1422  	tenant := ses.GetTenantInfo()
  1423  
  1424  	//step1 : create the role
  1425  	return InitRole(execCtx.reqCtx, ses.(*Session), tenant, cr)
  1426  }
  1427  
  1428  // handleDropRole drops the role
  1429  func handleDropRole(ses FeSession, execCtx *ExecCtx, dr *tree.DropRole) error {
  1430  	return doDropRole(execCtx.reqCtx, ses.(*Session), dr)
  1431  }
  1432  
  1433  func handleCreateFunction(ses FeSession, execCtx *ExecCtx, cf *tree.CreateFunction) error {
  1434  	tenant := ses.GetTenantInfo()
  1435  	return InitFunction(ses.(*Session), execCtx, tenant, cf)
  1436  }
  1437  
  1438  func handleDropFunction(ses FeSession, execCtx *ExecCtx, df *tree.DropFunction, proc *process.Process) error {
  1439  	return doDropFunction(execCtx.reqCtx, ses.(*Session), df, func(path string) error {
  1440  		return proc.FileService.Delete(execCtx.reqCtx, path)
  1441  	})
  1442  }
  1443  func handleCreateProcedure(ses FeSession, execCtx *ExecCtx, cp *tree.CreateProcedure) error {
  1444  	tenant := ses.GetTenantInfo()
  1445  
  1446  	return InitProcedure(execCtx.reqCtx, ses.(*Session), tenant, cp)
  1447  }
  1448  
  1449  func handleDropProcedure(ses FeSession, execCtx *ExecCtx, dp *tree.DropProcedure) error {
  1450  	return doDropProcedure(execCtx.reqCtx, ses.(*Session), dp)
  1451  }
  1452  
  1453  func handleCallProcedure(ses FeSession, execCtx *ExecCtx, call *tree.CallStmt, proc *process.Process) error {
  1454  	proto := ses.GetMysqlProtocol()
  1455  	results, err := doInterpretCall(execCtx.reqCtx, ses.(*Session), call)
  1456  	if err != nil {
  1457  		return err
  1458  	}
  1459  
  1460  	ses.SetMysqlResultSet(nil)
  1461  
  1462  	resp := NewGeneralOkResponse(COM_QUERY, ses.GetTxnHandler().GetServerStatus())
  1463  
  1464  	if len(results) == 0 {
  1465  		if err := proto.SendResponse(execCtx.reqCtx, resp); err != nil {
  1466  			return moerr.NewInternalError(execCtx.reqCtx, "routine send response failed. error:%v ", err)
  1467  		}
  1468  	} else {
  1469  		for i, result := range results {
  1470  			mer := NewMysqlExecutionResult(0, 0, 0, 0, result.(*MysqlResultSet))
  1471  			resp = ses.SetNewResponse(ResultResponse, 0, int(COM_QUERY), mer, i == len(results)-1)
  1472  			if err := proto.SendResponse(execCtx.reqCtx, resp); err != nil {
  1473  				return moerr.NewInternalError(execCtx.reqCtx, "routine send response failed. error:%v ", err)
  1474  			}
  1475  		}
  1476  	}
  1477  	return nil
  1478  }
  1479  
  1480  // handleGrantRole grants the role
  1481  func handleGrantRole(ses FeSession, execCtx *ExecCtx, gr *tree.GrantRole) error {
  1482  	return doGrantRole(execCtx.reqCtx, ses.(*Session), gr)
  1483  }
  1484  
  1485  // handleRevokeRole revokes the role
  1486  func handleRevokeRole(ses FeSession, execCtx *ExecCtx, rr *tree.RevokeRole) error {
  1487  	return doRevokeRole(execCtx.reqCtx, ses.(*Session), rr)
  1488  }
  1489  
  1490  // handleGrantRole grants the privilege to the role
  1491  func handleGrantPrivilege(ses FeSession, execCtx *ExecCtx, gp *tree.GrantPrivilege) error {
  1492  	return doGrantPrivilege(execCtx.reqCtx, ses, gp)
  1493  }
  1494  
  1495  // handleRevokePrivilege revokes the privilege from the user or role
  1496  func handleRevokePrivilege(ses FeSession, execCtx *ExecCtx, rp *tree.RevokePrivilege) error {
  1497  	return doRevokePrivilege(execCtx.reqCtx, ses, rp)
  1498  }
  1499  
  1500  // handleSwitchRole switches the role to another role
  1501  func handleSwitchRole(ses FeSession, execCtx *ExecCtx, sr *tree.SetRole) error {
  1502  	return doSwitchRole(execCtx.reqCtx, ses.(*Session), sr)
  1503  }
  1504  
  1505  func doKill(ses *Session, execCtx *ExecCtx, k *tree.Kill) error {
  1506  	var err error
  1507  	//true: kill a connection
  1508  	//false: kill a query in a connection
  1509  	idThatKill := uint64(ses.GetConnectionID())
  1510  	if !k.Option.Exist || k.Option.Typ == tree.KillTypeConnection {
  1511  		err = getGlobalRtMgr().kill(execCtx.reqCtx, true, idThatKill, k.ConnectionId, "")
  1512  	} else {
  1513  		err = getGlobalRtMgr().kill(execCtx.reqCtx, false, idThatKill, k.ConnectionId, k.StmtOption.StatementId)
  1514  	}
  1515  	return err
  1516  }
  1517  
  1518  // handleKill kill a connection or query
  1519  func handleKill(ses *Session, execCtx *ExecCtx, k *tree.Kill) error {
  1520  	err := doKill(ses, execCtx, k)
  1521  	if err != nil {
  1522  		return err
  1523  	}
  1524  	return err
  1525  }
  1526  
  1527  // handleShowAccounts lists the info of accounts
  1528  func handleShowAccounts(ses FeSession, execCtx *ExecCtx, sa *tree.ShowAccounts) error {
  1529  	err := doShowAccounts(execCtx.reqCtx, ses.(*Session), sa)
  1530  	if err != nil {
  1531  		return err
  1532  	}
  1533  	return err
  1534  }
  1535  
  1536  // handleShowCollation lists the info of collation
  1537  func handleShowCollation(ses FeSession, execCtx *ExecCtx, sc *tree.ShowCollation) error {
  1538  	err := doShowCollation(ses.(*Session), execCtx, execCtx.proc, sc)
  1539  	if err != nil {
  1540  		return err
  1541  	}
  1542  	return err
  1543  }
  1544  
  1545  func doShowCollation(ses *Session, execCtx *ExecCtx, proc *process.Process, sc *tree.ShowCollation) error {
  1546  	var err error
  1547  	var bat *batch.Batch
  1548  	// var outputBatches []*batch.Batch
  1549  
  1550  	// Construct the columns.
  1551  	col1 := new(MysqlColumn)
  1552  	col1.SetColumnType(defines.MYSQL_TYPE_VAR_STRING)
  1553  	col1.SetName("Collation")
  1554  
  1555  	col2 := new(MysqlColumn)
  1556  	col2.SetColumnType(defines.MYSQL_TYPE_VAR_STRING)
  1557  	col2.SetName("Charset")
  1558  
  1559  	col3 := new(MysqlColumn)
  1560  	col3.SetColumnType(defines.MYSQL_TYPE_LONGLONG)
  1561  	col3.SetName("Id")
  1562  
  1563  	col4 := new(MysqlColumn)
  1564  	col4.SetColumnType(defines.MYSQL_TYPE_VAR_STRING)
  1565  	col4.SetName("Default")
  1566  
  1567  	col5 := new(MysqlColumn)
  1568  	col5.SetColumnType(defines.MYSQL_TYPE_VAR_STRING)
  1569  	col5.SetName("Compiled")
  1570  
  1571  	col6 := new(MysqlColumn)
  1572  	col6.SetColumnType(defines.MYSQL_TYPE_LONG)
  1573  	col6.SetName("Sortlen")
  1574  
  1575  	col7 := new(MysqlColumn)
  1576  	col7.SetColumnType(defines.MYSQL_TYPE_VAR_STRING)
  1577  	col7.SetName("Pad_attribute")
  1578  
  1579  	mrs := ses.GetMysqlResultSet()
  1580  	mrs.AddColumn(col1)
  1581  	mrs.AddColumn(col2)
  1582  	mrs.AddColumn(col3)
  1583  	mrs.AddColumn(col4)
  1584  	mrs.AddColumn(col5)
  1585  	mrs.AddColumn(col6)
  1586  	mrs.AddColumn(col7)
  1587  
  1588  	var hasLike = false
  1589  	var likePattern = ""
  1590  	var isIlike = false
  1591  	if sc.Like != nil {
  1592  		hasLike = true
  1593  		if sc.Like.Op == tree.ILIKE {
  1594  			isIlike = true
  1595  		}
  1596  		likePattern = strings.ToLower(sc.Like.Right.String())
  1597  	}
  1598  
  1599  	// Construct the rows.
  1600  	rows := make([][]interface{}, 0, len(Collations))
  1601  	for _, collation := range Collations {
  1602  		if hasLike {
  1603  			s := collation.collationName
  1604  			if isIlike {
  1605  				s = strings.ToLower(s)
  1606  			}
  1607  			if !WildcardMatch(likePattern, s) {
  1608  				continue
  1609  			}
  1610  		}
  1611  		row := make([]interface{}, 7)
  1612  		row[0] = collation.collationName
  1613  		row[1] = collation.charset
  1614  		row[2] = collation.id
  1615  		row[3] = collation.isDefault
  1616  		row[4] = collation.isCompiled
  1617  		row[5] = collation.sortLen
  1618  		row[6] = collation.padAttribute
  1619  		rows = append(rows, row)
  1620  	}
  1621  
  1622  	bat, err = constructCollationBatch(ses, rows)
  1623  	defer bat.Clean(proc.Mp())
  1624  	if err != nil {
  1625  		return err
  1626  	}
  1627  
  1628  	if sc.Where != nil {
  1629  		binder := plan2.NewDefaultBinder(execCtx.reqCtx, nil, nil, plan2.Type{Id: int32(types.T_varchar), Width: types.MaxVarcharLen}, []string{"collation", "charset", "id", "default", "compiled", "sortlen", "pad_attribute"})
  1630  		planExpr, err := binder.BindExpr(sc.Where.Expr, 0, false)
  1631  		if err != nil {
  1632  			return err
  1633  		}
  1634  
  1635  		executor, err := colexec.NewExpressionExecutor(proc, planExpr)
  1636  		if err != nil {
  1637  			return err
  1638  		}
  1639  		vec, err := executor.Eval(proc, []*batch.Batch{bat})
  1640  		if err != nil {
  1641  			executor.Free()
  1642  			return err
  1643  		}
  1644  
  1645  		bs := vector.MustFixedCol[bool](vec)
  1646  		sels := proc.Mp().GetSels()
  1647  		for i, b := range bs {
  1648  			if b {
  1649  				sels = append(sels, int64(i))
  1650  			}
  1651  		}
  1652  		executor.Free()
  1653  
  1654  		bat.Shrink(sels, false)
  1655  		proc.Mp().PutSels(sels)
  1656  		v0 := vector.MustStrCol(bat.Vecs[0])
  1657  		v1 := vector.MustStrCol(bat.Vecs[1])
  1658  		v2 := vector.MustFixedCol[int64](bat.Vecs[2])
  1659  		v3 := vector.MustStrCol(bat.Vecs[3])
  1660  		v4 := vector.MustStrCol(bat.Vecs[4])
  1661  		v5 := vector.MustFixedCol[int32](bat.Vecs[5])
  1662  		v6 := vector.MustStrCol(bat.Vecs[6])
  1663  		rows = rows[:len(v0)]
  1664  		for i := range v0 {
  1665  			rows[i][0] = v0[i]
  1666  			rows[i][1] = v1[i]
  1667  			rows[i][2] = v2[i]
  1668  			rows[i][3] = v3[i]
  1669  			rows[i][4] = v4[i]
  1670  			rows[i][5] = v5[i]
  1671  			rows[i][6] = v6[i]
  1672  		}
  1673  	}
  1674  
  1675  	//sort by name
  1676  	sort.Slice(rows, func(i, j int) bool {
  1677  		return rows[i][0].(string) < rows[j][0].(string)
  1678  	})
  1679  
  1680  	for _, row := range rows {
  1681  		mrs.AddRow(row)
  1682  	}
  1683  
  1684  	// oq := newFakeOutputQueue(mrs)
  1685  	// if err = fillResultSet(oq, bat, ses); err != nil {
  1686  	// 	return err
  1687  	// }
  1688  
  1689  	ses.SetMysqlResultSet(mrs)
  1690  	ses.rs = mysqlColDef2PlanResultColDef(mrs)
  1691  
  1692  	// save query result
  1693  	if openSaveQueryResult(execCtx.reqCtx, ses) {
  1694  		if err := saveQueryResult(execCtx.reqCtx, ses, bat); err != nil {
  1695  			return err
  1696  		}
  1697  		if err := saveQueryResultMeta(execCtx.reqCtx, ses); err != nil {
  1698  			return err
  1699  		}
  1700  	}
  1701  
  1702  	return err
  1703  }
  1704  
  1705  func handleShowSubscriptions(ses FeSession, execCtx *ExecCtx, ss *tree.ShowSubscriptions) error {
  1706  	err := doShowSubscriptions(execCtx.reqCtx, ses.(*Session), ss)
  1707  	if err != nil {
  1708  		return err
  1709  	}
  1710  	return err
  1711  }
  1712  
  1713  func doShowBackendServers(ses *Session) error {
  1714  	// Construct the columns.
  1715  	col1 := new(MysqlColumn)
  1716  	col1.SetColumnType(defines.MYSQL_TYPE_VARCHAR)
  1717  	col1.SetName("UUID")
  1718  
  1719  	col2 := new(MysqlColumn)
  1720  	col2.SetColumnType(defines.MYSQL_TYPE_VARCHAR)
  1721  	col2.SetName("Address")
  1722  
  1723  	col3 := new(MysqlColumn)
  1724  	col3.SetColumnType(defines.MYSQL_TYPE_VARCHAR)
  1725  	col3.SetName("Work State")
  1726  
  1727  	col4 := new(MysqlColumn)
  1728  	col4.SetColumnType(defines.MYSQL_TYPE_VARCHAR)
  1729  	col4.SetName("Labels")
  1730  
  1731  	mrs := ses.GetMysqlResultSet()
  1732  	mrs.AddColumn(col1)
  1733  	mrs.AddColumn(col2)
  1734  	mrs.AddColumn(col3)
  1735  	mrs.AddColumn(col4)
  1736  
  1737  	var filterLabels = func(labels map[string]string) map[string]string {
  1738  		var reservedLabels = map[string]struct{}{
  1739  			"os_user":      {},
  1740  			"os_sudouser":  {},
  1741  			"program_name": {},
  1742  		}
  1743  		for k := range labels {
  1744  			if _, ok := reservedLabels[k]; ok || strings.HasPrefix(k, "_") {
  1745  				delete(labels, k)
  1746  			}
  1747  		}
  1748  		return labels
  1749  	}
  1750  
  1751  	var appendFn = func(s *metadata.CNService) {
  1752  		row := make([]interface{}, 4)
  1753  		row[0] = s.ServiceID
  1754  		row[1] = s.SQLAddress
  1755  		row[2] = s.WorkState.String()
  1756  		var labelStr string
  1757  		for key, value := range s.Labels {
  1758  			labelStr += fmt.Sprintf("%s:%s;", key, strings.Join(value.Labels, ","))
  1759  		}
  1760  		row[3] = labelStr
  1761  		mrs.AddRow(row)
  1762  	}
  1763  
  1764  	tenant := ses.GetTenantInfo().GetTenant()
  1765  	var se clusterservice.Selector
  1766  	labels, err := ParseLabel(getLabelPart(ses.GetUserName()))
  1767  	if err != nil {
  1768  		return err
  1769  	}
  1770  	labels["account"] = tenant
  1771  	se = clusterservice.NewSelector().SelectByLabel(
  1772  		filterLabels(labels), clusterservice.Contain)
  1773  	if isSysTenant(tenant) {
  1774  		u := ses.GetTenantInfo().GetUser()
  1775  		// For super use dump and root, we should list all servers.
  1776  		if isSuperUser(u) {
  1777  			clusterservice.GetMOCluster().GetCNService(
  1778  				clusterservice.NewSelectAll(), func(s metadata.CNService) bool {
  1779  					appendFn(&s)
  1780  					return true
  1781  				})
  1782  		} else {
  1783  			route.RouteForSuperTenant(se, u, nil, appendFn)
  1784  		}
  1785  	} else {
  1786  		route.RouteForCommonTenant(se, nil, appendFn)
  1787  	}
  1788  	return nil
  1789  }
  1790  
  1791  func handleShowBackendServers(ses FeSession, execCtx *ExecCtx) error {
  1792  	var err error
  1793  	if err := doShowBackendServers(ses.(*Session)); err != nil {
  1794  		return err
  1795  	}
  1796  	return err
  1797  }
  1798  
  1799  func handleEmptyStmt(ses FeSession, execCtx *ExecCtx, stmt *tree.EmptyStmt) error {
  1800  	var err error
  1801  	return err
  1802  }
  1803  
  1804  func GetExplainColumns(ctx context.Context, explainColName string) ([]interface{}, error) {
  1805  	cols := []*plan2.ColDef{
  1806  		{Typ: plan2.Type{Id: int32(types.T_varchar)}, Name: explainColName},
  1807  	}
  1808  	columns := make([]interface{}, len(cols))
  1809  	var err error = nil
  1810  	for i, col := range cols {
  1811  		c := new(MysqlColumn)
  1812  		c.SetName(col.Name)
  1813  		err = convertEngineTypeToMysqlType(ctx, types.T(col.Typ.Id), c)
  1814  		if err != nil {
  1815  			return nil, err
  1816  		}
  1817  		columns[i] = c
  1818  	}
  1819  	return columns, err
  1820  }
  1821  
  1822  func getExplainOption(reqCtx context.Context, options []tree.OptionElem) (*explain.ExplainOptions, error) {
  1823  	es := explain.NewExplainDefaultOptions()
  1824  	if options == nil {
  1825  		return es, nil
  1826  	} else {
  1827  		for _, v := range options {
  1828  			if strings.EqualFold(v.Name, "VERBOSE") {
  1829  				if strings.EqualFold(v.Value, "TRUE") || v.Value == "NULL" {
  1830  					es.Verbose = true
  1831  				} else if strings.EqualFold(v.Value, "FALSE") {
  1832  					es.Verbose = false
  1833  				} else {
  1834  					return nil, moerr.NewInvalidInput(reqCtx, "invalid explain option '%s', valud '%s'", v.Name, v.Value)
  1835  				}
  1836  			} else if strings.EqualFold(v.Name, "ANALYZE") {
  1837  				if strings.EqualFold(v.Value, "TRUE") || v.Value == "NULL" {
  1838  					es.Analyze = true
  1839  				} else if strings.EqualFold(v.Value, "FALSE") {
  1840  					es.Analyze = false
  1841  				} else {
  1842  					return nil, moerr.NewInvalidInput(reqCtx, "invalid explain option '%s', valud '%s'", v.Name, v.Value)
  1843  				}
  1844  			} else if strings.EqualFold(v.Name, "FORMAT") {
  1845  				if strings.EqualFold(v.Value, "TEXT") {
  1846  					es.Format = explain.EXPLAIN_FORMAT_TEXT
  1847  				} else if strings.EqualFold(v.Value, "JSON") {
  1848  					return nil, moerr.NewNotSupported(reqCtx, "Unsupport explain format '%s'", v.Value)
  1849  				} else if strings.EqualFold(v.Value, "DOT") {
  1850  					return nil, moerr.NewNotSupported(reqCtx, "Unsupport explain format '%s'", v.Value)
  1851  				} else {
  1852  					return nil, moerr.NewInvalidInput(reqCtx, "invalid explain option '%s', valud '%s'", v.Name, v.Value)
  1853  				}
  1854  			} else {
  1855  				return nil, moerr.NewInvalidInput(reqCtx, "invalid explain option '%s', valud '%s'", v.Name, v.Value)
  1856  			}
  1857  		}
  1858  		return es, nil
  1859  	}
  1860  }
  1861  
  1862  func buildMoExplainQuery(execCtx *ExecCtx, explainColName string, buffer *explain.ExplainDataBuffer, session *Session, fill outputCallBackFunc) error {
  1863  	bat := batch.New(true, []string{explainColName})
  1864  	rs := buffer.Lines
  1865  	vs := make([][]byte, len(rs))
  1866  
  1867  	count := 0
  1868  	for _, r := range rs {
  1869  		str := []byte(r)
  1870  		vs[count] = str
  1871  		count++
  1872  	}
  1873  	vs = vs[:count]
  1874  	vec := vector.NewVec(types.T_varchar.ToType())
  1875  	defer vec.Free(session.GetMemPool())
  1876  	vector.AppendBytesList(vec, vs, nil, session.GetMemPool())
  1877  	bat.Vecs[0] = vec
  1878  	bat.SetRowCount(count)
  1879  
  1880  	err := fill(session, execCtx, bat)
  1881  	if err != nil {
  1882  		return err
  1883  	}
  1884  	// to trigger save result meta
  1885  	err = fill(session, execCtx, nil)
  1886  	return err
  1887  }
  1888  
  1889  func buildPlan(reqCtx context.Context, ses FeSession, ctx plan2.CompilerContext, stmt tree.Statement) (*plan2.Plan, error) {
  1890  	var ret *plan2.Plan
  1891  	var err error
  1892  
  1893  	txnOp := ctx.GetProcess().TxnOperator
  1894  	start := time.Now()
  1895  	seq := uint64(0)
  1896  	if txnOp != nil {
  1897  		seq = txnOp.NextSequence()
  1898  		txnTrace.GetService().AddTxnDurationAction(
  1899  			txnOp,
  1900  			client.BuildPlanEvent,
  1901  			seq,
  1902  			0,
  1903  			0,
  1904  			err)
  1905  	}
  1906  
  1907  	defer func() {
  1908  		cost := time.Since(start)
  1909  
  1910  		if txnOp != nil {
  1911  			txnTrace.GetService().AddTxnDurationAction(
  1912  				txnOp,
  1913  				client.BuildPlanEvent,
  1914  				seq,
  1915  				0,
  1916  				cost,
  1917  				err)
  1918  		}
  1919  		v2.TxnStatementBuildPlanDurationHistogram.Observe(cost.Seconds())
  1920  	}()
  1921  
  1922  	stats := statistic.StatsInfoFromContext(reqCtx)
  1923  	stats.PlanStart()
  1924  	defer stats.PlanEnd()
  1925  
  1926  	isPrepareStmt := false
  1927  	if ses != nil {
  1928  		var accId uint32
  1929  		accId, err = defines.GetAccountId(reqCtx)
  1930  		if err != nil {
  1931  			return nil, err
  1932  		}
  1933  		ses.SetAccountId(accId)
  1934  		if len(ses.GetSql()) > 8 {
  1935  			prefix := strings.ToLower(ses.GetSql()[:8])
  1936  			isPrepareStmt = prefix == "execute " || prefix == "prepare "
  1937  		}
  1938  	}
  1939  	if s, ok := stmt.(*tree.Insert); ok {
  1940  		if _, ok := s.Rows.Select.(*tree.ValuesClause); ok {
  1941  			ret, err = plan2.BuildPlan(ctx, stmt, isPrepareStmt)
  1942  			if err != nil {
  1943  				return nil, err
  1944  			}
  1945  		}
  1946  	}
  1947  	if ret != nil {
  1948  		if ses != nil && ses.GetTenantInfo() != nil && !ses.IsBackgroundSession() {
  1949  			err = authenticateCanExecuteStatementAndPlan(reqCtx, ses.(*Session), stmt, ret)
  1950  			if err != nil {
  1951  				return nil, err
  1952  			}
  1953  		}
  1954  		return ret, err
  1955  	}
  1956  	switch stmt := stmt.(type) {
  1957  	case *tree.Select, *tree.ParenSelect, *tree.ValuesStatement,
  1958  		*tree.Update, *tree.Delete, *tree.Insert,
  1959  		*tree.ShowDatabases, *tree.ShowTables, *tree.ShowSequences, *tree.ShowColumns, *tree.ShowColumnNumber, *tree.ShowTableNumber,
  1960  		*tree.ShowCreateDatabase, *tree.ShowCreateTable, *tree.ShowIndex,
  1961  		*tree.ExplainStmt, *tree.ExplainAnalyze:
  1962  		opt := plan2.NewBaseOptimizer(ctx)
  1963  		optimized, err := opt.Optimize(stmt, isPrepareStmt)
  1964  		if err != nil {
  1965  			return nil, err
  1966  		}
  1967  		ret = &plan2.Plan{
  1968  			Plan: &plan2.Plan_Query{
  1969  				Query: optimized,
  1970  			},
  1971  		}
  1972  	default:
  1973  		ret, err = plan2.BuildPlan(ctx, stmt, isPrepareStmt)
  1974  	}
  1975  	if ret != nil {
  1976  		ret.IsPrepare = isPrepareStmt
  1977  		if ses != nil && ses.GetTenantInfo() != nil && !ses.IsBackgroundSession() {
  1978  			err = authenticateCanExecuteStatementAndPlan(reqCtx, ses.(*Session), stmt, ret)
  1979  			if err != nil {
  1980  				return nil, err
  1981  			}
  1982  		}
  1983  	}
  1984  	return ret, err
  1985  }
  1986  
  1987  func checkModify(plan0 *plan.Plan, ses FeSession) bool {
  1988  	if plan0 == nil {
  1989  		return true
  1990  	}
  1991  	checkFn := func(db string, tableName string, tableId uint64, version uint32) bool {
  1992  		_, tableDef := ses.GetTxnCompileCtx().Resolve(db, tableName, plan.Snapshot{TS: &timestamp.Timestamp{}})
  1993  		if tableDef == nil {
  1994  			return true
  1995  		}
  1996  		if tableDef.Version != version || tableDef.TblId != tableId {
  1997  			return true
  1998  		}
  1999  		return false
  2000  	}
  2001  	switch p := plan0.Plan.(type) {
  2002  	case *plan.Plan_Query:
  2003  		for i := range p.Query.Nodes {
  2004  			if def := p.Query.Nodes[i].TableDef; def != nil {
  2005  				if p.Query.Nodes[i].ObjRef == nil || checkFn(p.Query.Nodes[i].ObjRef.SchemaName, def.Name, def.TblId, def.Version) {
  2006  					return true
  2007  				}
  2008  			}
  2009  			if ctx := p.Query.Nodes[i].InsertCtx; ctx != nil {
  2010  				if ctx.Ref == nil || checkFn(ctx.Ref.SchemaName, ctx.TableDef.Name, ctx.TableDef.TblId, ctx.TableDef.Version) {
  2011  					return true
  2012  				}
  2013  			}
  2014  			if ctx := p.Query.Nodes[i].ReplaceCtx; ctx != nil {
  2015  				if ctx.Ref == nil || checkFn(ctx.Ref.SchemaName, ctx.TableDef.Name, ctx.TableDef.TblId, ctx.TableDef.Version) {
  2016  					return true
  2017  				}
  2018  			}
  2019  			if ctx := p.Query.Nodes[i].DeleteCtx; ctx != nil {
  2020  				if ctx.Ref == nil || checkFn(ctx.Ref.SchemaName, ctx.TableDef.Name, ctx.TableDef.TblId, ctx.TableDef.Version) {
  2021  					return true
  2022  				}
  2023  			}
  2024  			if ctx := p.Query.Nodes[i].PreInsertCtx; ctx != nil {
  2025  				if ctx.Ref == nil || checkFn(ctx.Ref.SchemaName, ctx.TableDef.Name, ctx.TableDef.TblId, ctx.TableDef.Version) {
  2026  					return true
  2027  				}
  2028  			}
  2029  			if ctx := p.Query.Nodes[i].PreInsertCtx; ctx != nil {
  2030  				if ctx.Ref == nil || checkFn(ctx.Ref.SchemaName, ctx.TableDef.Name, ctx.TableDef.TblId, ctx.TableDef.Version) {
  2031  					return true
  2032  				}
  2033  			}
  2034  			if ctx := p.Query.Nodes[i].OnDuplicateKey; ctx != nil {
  2035  				if p.Query.Nodes[i].ObjRef == nil || checkFn(p.Query.Nodes[i].ObjRef.SchemaName, ctx.TableName, ctx.TableId, ctx.TableVersion) {
  2036  					return true
  2037  				}
  2038  			}
  2039  		}
  2040  	default:
  2041  	}
  2042  	return false
  2043  }
  2044  
  2045  var GetComputationWrapper = func(execCtx *ExecCtx, db string, user string, eng engine.Engine, proc *process.Process, ses *Session) ([]ComputationWrapper, error) {
  2046  	var cws []ComputationWrapper = nil
  2047  	if cached := ses.getCachedPlan(execCtx.input.getSql()); cached != nil {
  2048  		for i, stmt := range cached.stmts {
  2049  			tcw := InitTxnComputationWrapper(ses, stmt, proc)
  2050  			tcw.plan = cached.plans[i]
  2051  			cws = append(cws, tcw)
  2052  		}
  2053  
  2054  		return cws, nil
  2055  	}
  2056  
  2057  	var stmts []tree.Statement = nil
  2058  	var cmdFieldStmt *InternalCmdFieldList
  2059  	var err error
  2060  	// if the input is an option ast, we should use it directly
  2061  	if execCtx.input.getStmt() != nil {
  2062  		stmts = append(stmts, execCtx.input.getStmt())
  2063  	} else if isCmdFieldListSql(execCtx.input.getSql()) {
  2064  		cmdFieldStmt, err = parseCmdFieldList(execCtx.reqCtx, execCtx.input.getSql())
  2065  		if err != nil {
  2066  			return nil, err
  2067  		}
  2068  		stmts = append(stmts, cmdFieldStmt)
  2069  	} else {
  2070  		stmts, err = parseSql(execCtx)
  2071  		if err != nil {
  2072  			return nil, err
  2073  		}
  2074  	}
  2075  
  2076  	for _, stmt := range stmts {
  2077  		cws = append(cws, InitTxnComputationWrapper(ses, stmt, proc))
  2078  	}
  2079  	return cws, nil
  2080  }
  2081  
  2082  func parseSql(execCtx *ExecCtx) (stmts []tree.Statement, err error) {
  2083  	var v interface{}
  2084  	var origin interface{}
  2085  	v, err = execCtx.ses.GetGlobalVar(execCtx.reqCtx, "lower_case_table_names")
  2086  	if err != nil {
  2087  		v = int64(1)
  2088  	}
  2089  	origin, err = execCtx.ses.GetGlobalVar(execCtx.reqCtx, "keep_user_target_list_in_result")
  2090  	if err != nil {
  2091  		origin = int64(0)
  2092  	}
  2093  	stmts, err = parsers.Parse(execCtx.reqCtx, dialect.MYSQL, execCtx.input.getSql(), v.(int64), origin.(int64))
  2094  	if err != nil {
  2095  		return nil, err
  2096  	}
  2097  	return
  2098  }
  2099  
  2100  func incTransactionCounter(tenant string) {
  2101  	metric.TransactionCounter(tenant).Inc()
  2102  }
  2103  
  2104  func incTransactionErrorsCounter(tenant string, t metric.SQLType) {
  2105  	if t == metric.SQLTypeRollback {
  2106  		return
  2107  	}
  2108  	metric.TransactionErrorsCounter(tenant, t).Inc()
  2109  }
  2110  
  2111  func incStatementErrorsCounter(tenant string, stmt tree.Statement) {
  2112  	metric.StatementErrorsCounter(tenant, getStatementType(stmt).GetQueryType()).Inc()
  2113  }
  2114  
  2115  // authenticateUserCanExecuteStatement checks the user can execute the statement
  2116  func authenticateUserCanExecuteStatement(reqCtx context.Context, ses *Session, stmt tree.Statement) error {
  2117  	reqCtx, span := trace.Debug(reqCtx, "authenticateUserCanExecuteStatement")
  2118  	defer span.End()
  2119  	if getGlobalPu().SV.SkipCheckPrivilege {
  2120  		return nil
  2121  	}
  2122  
  2123  	if ses.skipAuthForSpecialUser() {
  2124  		return nil
  2125  	}
  2126  	var havePrivilege bool
  2127  	var err error
  2128  	if ses.GetTenantInfo() != nil {
  2129  		ses.SetPrivilege(determinePrivilegeSetOfStatement(stmt))
  2130  
  2131  		// can or not execute in retricted status
  2132  		if ses.getRoutine() != nil && ses.getRoutine().isRestricted() && !ses.GetPrivilege().canExecInRestricted {
  2133  			return moerr.NewInternalError(reqCtx, "do not have privilege to execute the statement")
  2134  		}
  2135  
  2136  		havePrivilege, err = authenticateUserCanExecuteStatementWithObjectTypeAccountAndDatabase(reqCtx, ses, stmt)
  2137  		if err != nil {
  2138  			return err
  2139  		}
  2140  
  2141  		if !havePrivilege {
  2142  			err = moerr.NewInternalError(reqCtx, "do not have privilege to execute the statement")
  2143  			return err
  2144  		}
  2145  
  2146  		havePrivilege, err = authenticateUserCanExecuteStatementWithObjectTypeNone(reqCtx, ses, stmt)
  2147  		if err != nil {
  2148  			return err
  2149  		}
  2150  
  2151  		if !havePrivilege {
  2152  			err = moerr.NewInternalError(reqCtx, "do not have privilege to execute the statement")
  2153  			return err
  2154  		}
  2155  	}
  2156  	return err
  2157  }
  2158  
  2159  // authenticateCanExecuteStatementAndPlan checks the user can execute the statement and its plan
  2160  func authenticateCanExecuteStatementAndPlan(reqCtx context.Context, ses *Session, stmt tree.Statement, p *plan.Plan) error {
  2161  	_, task := gotrace.NewTask(reqCtx, "frontend.authenticateCanExecuteStatementAndPlan")
  2162  	defer task.End()
  2163  	if getGlobalPu().SV.SkipCheckPrivilege {
  2164  		return nil
  2165  	}
  2166  
  2167  	if ses.skipAuthForSpecialUser() {
  2168  		return nil
  2169  	}
  2170  	yes, err := authenticateUserCanExecuteStatementWithObjectTypeDatabaseAndTable(reqCtx, ses, stmt, p)
  2171  	if err != nil {
  2172  		return err
  2173  	}
  2174  	if !yes {
  2175  		return moerr.NewInternalError(reqCtx, "do not have privilege to execute the statement")
  2176  	}
  2177  	return nil
  2178  }
  2179  
  2180  // authenticatePrivilegeOfPrepareAndExecute checks the user can execute the Prepare or Execute statement
  2181  func authenticateUserCanExecutePrepareOrExecute(reqCtx context.Context, ses *Session, stmt tree.Statement, p *plan.Plan) error {
  2182  	_, task := gotrace.NewTask(reqCtx, "frontend.authenticateUserCanExecutePrepareOrExecute")
  2183  	defer task.End()
  2184  	if getGlobalPu().SV.SkipCheckPrivilege {
  2185  		return nil
  2186  	}
  2187  	err := authenticateUserCanExecuteStatement(reqCtx, ses, stmt)
  2188  	if err != nil {
  2189  		return err
  2190  	}
  2191  	err = authenticateCanExecuteStatementAndPlan(reqCtx, ses, stmt, p)
  2192  	if err != nil {
  2193  		return err
  2194  	}
  2195  	return err
  2196  }
  2197  
  2198  // canExecuteStatementInUncommittedTxn checks the user can execute the statement in an uncommitted transaction
  2199  func canExecuteStatementInUncommittedTransaction(reqCtx context.Context, ses FeSession, stmt tree.Statement) error {
  2200  	can, err := statementCanBeExecutedInUncommittedTransaction(reqCtx, ses, stmt)
  2201  	if err != nil {
  2202  		return err
  2203  	}
  2204  	if !can {
  2205  		//is ddl statement
  2206  		if IsCreateDropDatabase(stmt) {
  2207  			return moerr.NewInternalError(reqCtx, createDropDatabaseErrorInfo())
  2208  		} else if IsDDL(stmt) {
  2209  			return moerr.NewInternalError(reqCtx, onlyCreateStatementErrorInfo())
  2210  		} else if IsAdministrativeStatement(stmt) {
  2211  			return moerr.NewInternalError(reqCtx, administrativeCommandIsUnsupportedInTxnErrorInfo())
  2212  		} else {
  2213  			return moerr.NewInternalError(reqCtx, unclassifiedStatementInUncommittedTxnErrorInfo())
  2214  		}
  2215  	}
  2216  	return nil
  2217  }
  2218  
  2219  func processLoadLocal(ses FeSession, execCtx *ExecCtx, param *tree.ExternParam, writer *io.PipeWriter) (err error) {
  2220  	proto := ses.GetMysqlProtocol()
  2221  	defer func() {
  2222  		err2 := writer.Close()
  2223  		if err == nil {
  2224  			err = err2
  2225  		}
  2226  	}()
  2227  	err = plan2.InitInfileParam(param)
  2228  	if err != nil {
  2229  		return
  2230  	}
  2231  	err = proto.sendLocalInfileRequest(param.Filepath)
  2232  	if err != nil {
  2233  		return
  2234  	}
  2235  	start := time.Now()
  2236  	var msg interface{}
  2237  	msg, err = proto.GetTcpConnection().Read(goetty.ReadOptions{})
  2238  	if err != nil {
  2239  		proto.SetSequenceID(proto.GetSequenceId() + 1)
  2240  		if errors.Is(err, errorInvalidLength0) {
  2241  			return nil
  2242  		}
  2243  		if moerr.IsMoErrCode(err, moerr.ErrInvalidInput) {
  2244  			err = moerr.NewInvalidInput(execCtx.reqCtx, "cannot read '%s' from client,please check the file path, user privilege and if client start with --local-infile", param.Filepath)
  2245  		}
  2246  		return
  2247  	}
  2248  
  2249  	packet, ok := msg.(*Packet)
  2250  	if !ok {
  2251  		proto.SetSequenceID(proto.GetSequenceId() + 1)
  2252  		err = moerr.NewInvalidInput(execCtx.reqCtx, "invalid packet")
  2253  		return
  2254  	}
  2255  
  2256  	proto.SetSequenceID(uint8(packet.SequenceID + 1))
  2257  	seq := uint8(packet.SequenceID + 1)
  2258  	length := packet.Length
  2259  	if length == 0 {
  2260  		return
  2261  	}
  2262  	ses.CountPayload(len(packet.Payload))
  2263  
  2264  	skipWrite := false
  2265  	// If inner error occurs(unexpected or expected(ctrl-c)), proc.LoadLocalReader will be closed.
  2266  	// Then write will return error, but we need to read the rest of the data and not write it to pipe.
  2267  	// So we need a flag[skipWrite] to tell us whether we need to write the data to pipe.
  2268  	// https://github.com/matrixorigin/matrixone/issues/6665#issuecomment-1422236478
  2269  
  2270  	_, err = writer.Write(packet.Payload)
  2271  	if err != nil {
  2272  		skipWrite = true // next, we just need read the rest of the data,no need to write it to pipe.
  2273  		logError(ses, ses.GetDebugString(),
  2274  			"Failed to load local file",
  2275  			zap.String("path", param.Filepath),
  2276  			zap.Error(err))
  2277  	}
  2278  	epoch, printEvery, minReadTime, maxReadTime, minWriteTime, maxWriteTime := uint64(0), uint64(1024), 24*time.Hour, time.Nanosecond, 24*time.Hour, time.Nanosecond
  2279  	for {
  2280  		readStart := time.Now()
  2281  		msg, err = proto.GetTcpConnection().Read(goetty.ReadOptions{})
  2282  		if err != nil {
  2283  			if moerr.IsMoErrCode(err, moerr.ErrInvalidInput) {
  2284  				seq += 1
  2285  				proto.SetSequenceID(seq)
  2286  				err = nil
  2287  			}
  2288  			break
  2289  		}
  2290  		readTime := time.Since(readStart)
  2291  		if readTime > maxReadTime {
  2292  			maxReadTime = readTime
  2293  		}
  2294  		if readTime < minReadTime {
  2295  			minReadTime = readTime
  2296  		}
  2297  		packet, ok = msg.(*Packet)
  2298  		if !ok {
  2299  			err = moerr.NewInvalidInput(execCtx.reqCtx, "invalid packet")
  2300  			seq += 1
  2301  			proto.SetSequenceID(seq)
  2302  			break
  2303  		}
  2304  		seq = uint8(packet.SequenceID + 1)
  2305  		proto.SetSequenceID(seq)
  2306  		ses.CountPayload(len(packet.Payload))
  2307  
  2308  		writeStart := time.Now()
  2309  		if !skipWrite {
  2310  			_, err = writer.Write(packet.Payload)
  2311  			if err != nil {
  2312  				logError(ses, ses.GetDebugString(),
  2313  					"Failed to load local file",
  2314  					zap.String("path", param.Filepath),
  2315  					zap.Uint64("epoch", epoch),
  2316  					zap.Error(err))
  2317  				skipWrite = true
  2318  			}
  2319  			writeTime := time.Since(writeStart)
  2320  			if writeTime > maxWriteTime {
  2321  				maxWriteTime = writeTime
  2322  			}
  2323  			if writeTime < minWriteTime {
  2324  				minWriteTime = writeTime
  2325  			}
  2326  		}
  2327  		if epoch%printEvery == 0 {
  2328  			logDebugf(ses.GetDebugString(), "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())
  2329  			minReadTime, maxReadTime, minWriteTime, maxWriteTime = 24*time.Hour, time.Nanosecond, 24*time.Hour, time.Nanosecond
  2330  		}
  2331  		epoch += 1
  2332  	}
  2333  	logDebugf(ses.GetDebugString(), "load local '%s', read&write all data from client cost: %s", param.Filepath, time.Since(start))
  2334  	return
  2335  }
  2336  
  2337  func executeStmtWithResponse(ses *Session,
  2338  	execCtx *ExecCtx,
  2339  ) (err error) {
  2340  	var span trace.Span
  2341  	execCtx.reqCtx, span = trace.Start(execCtx.reqCtx, "executeStmtWithResponse",
  2342  		trace.WithKind(trace.SpanKindStatement))
  2343  	defer span.End(trace.WithStatementExtra(ses.GetTxnId(), ses.GetStmtId(), ses.GetSqlOfStmt()))
  2344  
  2345  	ses.SetQueryInProgress(true)
  2346  	ses.SetQueryStart(time.Now())
  2347  	ses.SetQueryInExecute(true)
  2348  	defer ses.SetQueryEnd(time.Now())
  2349  	defer ses.SetQueryInProgress(false)
  2350  
  2351  	err = executeStmtWithTxn(ses, execCtx)
  2352  	if err != nil {
  2353  		return err
  2354  	}
  2355  
  2356  	// TODO put in one txn
  2357  	// insert data after create table in "create table ... as select ..." stmt
  2358  	if ses.createAsSelectSql != "" {
  2359  		sql := ses.createAsSelectSql
  2360  		ses.createAsSelectSql = ""
  2361  		tempExecCtx := ExecCtx{
  2362  			ses:    ses,
  2363  			reqCtx: execCtx.reqCtx,
  2364  		}
  2365  		if err = doComQuery(ses, &tempExecCtx, &UserInput{sql: sql}); err != nil {
  2366  			return err
  2367  		}
  2368  	}
  2369  
  2370  	err = respClientWhenSuccess(ses, execCtx)
  2371  	if err != nil {
  2372  		return err
  2373  	}
  2374  
  2375  	return
  2376  }
  2377  
  2378  func executeStmtWithTxn(ses FeSession,
  2379  	execCtx *ExecCtx,
  2380  ) (err error) {
  2381  	if !ses.IsDerivedStmt() {
  2382  		err = executeStmtWithWorkspace(ses, execCtx)
  2383  	} else {
  2384  
  2385  		txnOp := ses.GetTxnHandler().GetTxn()
  2386  		//refresh proc txnOp
  2387  		execCtx.proc.TxnOperator = txnOp
  2388  
  2389  		err = dispatchStmt(ses, execCtx)
  2390  	}
  2391  	return
  2392  }
  2393  
  2394  func executeStmtWithWorkspace(ses FeSession,
  2395  	execCtx *ExecCtx,
  2396  ) (err error) {
  2397  	if ses.IsDerivedStmt() {
  2398  		return
  2399  	}
  2400  	var autocommit bool
  2401  	//derived stmt shares the same txn with ancestor.
  2402  	//it only executes select statements.
  2403  
  2404  	//7. pass or commit or rollback txn
  2405  	// defer transaction state management.
  2406  	defer func() {
  2407  		err = finishTxnFunc(ses, err, execCtx)
  2408  	}()
  2409  
  2410  	//1. start txn
  2411  	//special BEGIN,COMMIT,ROLLBACK
  2412  	beginStmt := false
  2413  	switch execCtx.stmt.(type) {
  2414  	case *tree.BeginTransaction:
  2415  		execCtx.txnOpt.byBegin = true
  2416  		beginStmt = true
  2417  	case *tree.CommitTransaction:
  2418  		execCtx.txnOpt.byCommit = true
  2419  		return nil
  2420  	case *tree.RollbackTransaction:
  2421  		execCtx.txnOpt.byRollback = true
  2422  		return nil
  2423  	}
  2424  
  2425  	autocommit, err = autocommitValue(execCtx.reqCtx, ses)
  2426  	if err != nil {
  2427  		return err
  2428  	}
  2429  
  2430  	execCtx.txnOpt.autoCommit = autocommit
  2431  	err = ses.GetTxnHandler().Create(execCtx)
  2432  	if err != nil {
  2433  		return err
  2434  	}
  2435  
  2436  	//skip BEGIN stmt
  2437  	if beginStmt {
  2438  		return err
  2439  	}
  2440  
  2441  	if ses.GetTxnHandler() == nil {
  2442  		panic("need txn handler")
  2443  	}
  2444  
  2445  	txnOp := ses.GetTxnHandler().GetTxn()
  2446  
  2447  	//refresh proc txnOp
  2448  	execCtx.proc.TxnOperator = txnOp
  2449  
  2450  	//!!!NOTE!!!: statement management
  2451  	//2. start statement on workspace
  2452  	txnOp.GetWorkspace().StartStatement()
  2453  	//3. end statement on workspace
  2454  	// defer Start/End Statement management, called after finishTxnFunc()
  2455  	defer func() {
  2456  		if ses.GetTxnHandler() == nil {
  2457  			panic("need txn handler 2")
  2458  		}
  2459  
  2460  		txnOp = ses.GetTxnHandler().GetTxn()
  2461  		if txnOp != nil {
  2462  			//most of the cases, txnOp will not nil except that "set autocommit = 1"
  2463  			//commit the txn immediately then the txnOp is nil.
  2464  			txnOp.GetWorkspace().EndStatement()
  2465  		}
  2466  	}()
  2467  
  2468  	err = executeStmtWithIncrStmt(ses, execCtx, txnOp)
  2469  
  2470  	return
  2471  }
  2472  
  2473  func executeStmtWithIncrStmt(ses FeSession,
  2474  	execCtx *ExecCtx,
  2475  	txnOp TxnOperator,
  2476  ) (err error) {
  2477  	if ses.IsDerivedStmt() {
  2478  		return
  2479  	}
  2480  	//3. increase statement id
  2481  	err = txnOp.GetWorkspace().IncrStatementID(execCtx.reqCtx, false)
  2482  	if err != nil {
  2483  		return err
  2484  	}
  2485  
  2486  	defer func() {
  2487  		if ses.GetTxnHandler() == nil {
  2488  			panic("need txn handler 3")
  2489  		}
  2490  
  2491  		//!!!NOTE!!!: it does not work
  2492  		//_, txnOp = ses.GetTxnHandler().GetTxn()
  2493  		//if txnOp != nil {
  2494  		//	err = rollbackLastStmt(execCtx, txnOp, err)
  2495  		//}
  2496  	}()
  2497  
  2498  	err = dispatchStmt(ses, execCtx)
  2499  	return
  2500  }
  2501  
  2502  func dispatchStmt(ses FeSession,
  2503  	execCtx *ExecCtx) (err error) {
  2504  	//5. check plan within txn
  2505  	if execCtx.cw.Plan() != nil {
  2506  		if checkModify(execCtx.cw.Plan(), ses) {
  2507  
  2508  			//plan changed
  2509  			//clear all cached plan and parse sql again
  2510  			var stmts []tree.Statement
  2511  			stmts, err = parseSql(execCtx)
  2512  			if err != nil {
  2513  				return err
  2514  			}
  2515  			if len(stmts) != len(execCtx.cws) {
  2516  				return moerr.NewInternalError(execCtx.reqCtx, "the count of stmts parsed from cached sql is not equal to cws length")
  2517  			}
  2518  			for i, cw := range execCtx.cws {
  2519  				cw.ResetPlanAndStmt(stmts[i])
  2520  			}
  2521  		}
  2522  	}
  2523  
  2524  	//6. execute stmt within txn
  2525  	switch sesImpl := ses.(type) {
  2526  	case *Session:
  2527  		return executeStmt(sesImpl, execCtx)
  2528  	case *backSession:
  2529  		return executeStmtInBack(sesImpl, execCtx)
  2530  	default:
  2531  		return moerr.NewInternalError(execCtx.reqCtx, "no such session implementation")
  2532  	}
  2533  }
  2534  
  2535  func executeStmt(ses *Session,
  2536  	execCtx *ExecCtx,
  2537  ) (err error) {
  2538  	if txw, ok := execCtx.cw.(*TxnComputationWrapper); ok {
  2539  		ses.GetTxnCompileCtx().tcw = txw
  2540  	}
  2541  
  2542  	// record goroutine info when ddl stmt run timeout
  2543  	switch execCtx.stmt.(type) {
  2544  	case *tree.CreateTable, *tree.DropTable, *tree.CreateDatabase, *tree.DropDatabase:
  2545  		_, span := trace.Start(execCtx.reqCtx, "executeStmtHung",
  2546  			trace.WithHungThreshold(time.Minute), // be careful with this options
  2547  			trace.WithProfileGoroutine(),
  2548  			trace.WithProfileTraceSecs(10*time.Second),
  2549  		)
  2550  		defer span.End()
  2551  	default:
  2552  	}
  2553  
  2554  	var cmpBegin time.Time
  2555  	var ret interface{}
  2556  
  2557  	switch execCtx.stmt.StmtKind().ExecLocation() {
  2558  	case tree.EXEC_IN_FRONTEND:
  2559  		return execInFrontend(ses, execCtx)
  2560  	case tree.EXEC_IN_ENGINE:
  2561  		//in the computation engine
  2562  	}
  2563  
  2564  	switch st := execCtx.stmt.(type) {
  2565  	case *tree.Select:
  2566  		if st.Ep != nil {
  2567  			if getGlobalPu().SV.DisableSelectInto {
  2568  				err = moerr.NewSyntaxError(execCtx.reqCtx, "Unsupport select statement")
  2569  				return
  2570  			}
  2571  			ses.InitExportConfig(st.Ep)
  2572  			defer func() {
  2573  				ses.ClearExportParam()
  2574  			}()
  2575  			err = doCheckFilePath(execCtx.reqCtx, ses, st.Ep)
  2576  			if err != nil {
  2577  				return
  2578  			}
  2579  		}
  2580  	case *tree.CreateDatabase:
  2581  		err = inputNameIsInvalid(execCtx.reqCtx, string(st.Name))
  2582  		if err != nil {
  2583  			return
  2584  		}
  2585  		if st.SubscriptionOption != nil && ses.GetTenantInfo() != nil && !ses.GetTenantInfo().IsAdminRole() {
  2586  			err = moerr.NewInternalError(execCtx.reqCtx, "only admin can create subscription")
  2587  			return
  2588  		}
  2589  		st.Sql = execCtx.sqlOfStmt
  2590  	case *tree.DropDatabase:
  2591  		err = inputNameIsInvalid(execCtx.reqCtx, string(st.Name))
  2592  		if err != nil {
  2593  			return
  2594  		}
  2595  		ses.InvalidatePrivilegeCache()
  2596  		// if the droped database is the same as the one in use, database must be reseted to empty.
  2597  		if string(st.Name) == ses.GetDatabaseName() {
  2598  			ses.SetDatabaseName("")
  2599  		}
  2600  	case *tree.ExplainAnalyze:
  2601  		ses.SetData(nil)
  2602  	case *tree.ShowTableStatus:
  2603  		ses.SetShowStmtType(ShowTableStatus)
  2604  		ses.SetData(nil)
  2605  	case *tree.Load:
  2606  		if st.Local {
  2607  			execCtx.proc.LoadLocalReader, execCtx.loadLocalWriter = io.Pipe()
  2608  		}
  2609  	case *tree.ShowGrants:
  2610  		if len(st.Username) == 0 {
  2611  			st.Username = execCtx.userName
  2612  		}
  2613  		if len(st.Hostname) == 0 || st.Hostname == "%" {
  2614  			st.Hostname = rootHost
  2615  		}
  2616  	}
  2617  
  2618  	defer func() {
  2619  		// Serialize the execution plan as json
  2620  		if cwft, ok := execCtx.cw.(*TxnComputationWrapper); ok {
  2621  			_ = cwft.RecordExecPlan(execCtx.reqCtx)
  2622  		}
  2623  	}()
  2624  
  2625  	cmpBegin = time.Now()
  2626  
  2627  	if ret, err = execCtx.cw.Compile(execCtx, ses.GetOutputCallback(execCtx)); err != nil {
  2628  		return
  2629  	}
  2630  
  2631  	defer func() {
  2632  		if c, ok := ret.(*compile.Compile); ok {
  2633  			c.Release()
  2634  		}
  2635  	}()
  2636  
  2637  	// cw.Compile may rewrite the stmt in the EXECUTE statement, we fetch the latest version
  2638  	//need to check again.
  2639  	execCtx.stmt = execCtx.cw.GetAst()
  2640  	switch execCtx.stmt.StmtKind().ExecLocation() {
  2641  	case tree.EXEC_IN_FRONTEND:
  2642  		return execInFrontend(ses, execCtx)
  2643  	case tree.EXEC_IN_ENGINE:
  2644  
  2645  	}
  2646  
  2647  	execCtx.runner = ret.(ComputationRunner)
  2648  
  2649  	// only log if build time is longer than 1s
  2650  	if time.Since(cmpBegin) > time.Second {
  2651  		logInfo(ses, ses.GetDebugString(), fmt.Sprintf("time of Exec.Build : %s", time.Since(cmpBegin).String()))
  2652  	}
  2653  
  2654  	//output result & status
  2655  	StmtKind := execCtx.stmt.StmtKind().OutputType()
  2656  	switch StmtKind {
  2657  	case tree.OUTPUT_RESULT_ROW:
  2658  		err = executeResultRowStmt(ses, execCtx)
  2659  		if err != nil {
  2660  			return err
  2661  		}
  2662  	case tree.OUTPUT_STATUS:
  2663  		err = executeStatusStmt(ses, execCtx)
  2664  		if err != nil {
  2665  			return err
  2666  		}
  2667  	case tree.OUTPUT_UNDEFINED:
  2668  		if _, ok := execCtx.stmt.(*tree.Execute); !ok {
  2669  			return moerr.NewInternalError(execCtx.reqCtx, "need set result type for %s", execCtx.sqlOfStmt)
  2670  		}
  2671  	}
  2672  
  2673  	return
  2674  }
  2675  
  2676  // execute query
  2677  func doComQuery(ses *Session, execCtx *ExecCtx, input *UserInput) (retErr error) {
  2678  	ses.GetTxnCompileCtx().SetExecCtx(execCtx)
  2679  	// set the batch buf for stream scan
  2680  	var inMemStreamScan []*kafka.Message
  2681  
  2682  	if batchValue, ok := execCtx.reqCtx.Value(defines.SourceScanResKey{}).([]*kafka.Message); ok {
  2683  		inMemStreamScan = batchValue
  2684  	}
  2685  
  2686  	beginInstant := time.Now()
  2687  	execCtx.reqCtx = appendStatementAt(execCtx.reqCtx, beginInstant)
  2688  	input.genSqlSourceType(ses)
  2689  	ses.SetShowStmtType(NotShowStatement)
  2690  	proto := ses.GetMysqlProtocol()
  2691  	ses.SetSql(input.getSql())
  2692  
  2693  	//the ses.GetUserName returns the user_name with the account_name.
  2694  	//here,we only need the user_name.
  2695  	userNameOnly := rootName
  2696  
  2697  	proc := ses.proc
  2698  	proc.Ctx = execCtx.reqCtx
  2699  
  2700  	proc.CopyVectorPool(ses.proc)
  2701  	proc.CopyValueScanBatch(ses.proc)
  2702  	proc.Id = ses.getNextProcessId()
  2703  	proc.Lim.Size = getGlobalPu().SV.ProcessLimitationSize
  2704  	proc.Lim.BatchRows = getGlobalPu().SV.ProcessLimitationBatchRows
  2705  	proc.Lim.MaxMsgSize = getGlobalPu().SV.MaxMessageSize
  2706  	proc.Lim.PartitionRows = getGlobalPu().SV.ProcessLimitationPartitionRows
  2707  	proc.SessionInfo = process.SessionInfo{
  2708  		User:                 ses.GetUserName(),
  2709  		Host:                 getGlobalPu().SV.Host,
  2710  		ConnectionID:         uint64(proto.ConnectionID()),
  2711  		Database:             ses.GetDatabaseName(),
  2712  		Version:              makeServerVersion(getGlobalPu(), serverVersion.Load().(string)),
  2713  		TimeZone:             ses.GetTimeZone(),
  2714  		StorageEngine:        getGlobalPu().StorageEngine,
  2715  		LastInsertID:         ses.GetLastInsertID(),
  2716  		SqlHelper:            ses.GetSqlHelper(),
  2717  		Buf:                  ses.GetBuffer(),
  2718  		SourceInMemScanBatch: inMemStreamScan,
  2719  	}
  2720  	proc.SetResolveVariableFunc(ses.txnCompileCtx.ResolveVariable)
  2721  	proc.InitSeq()
  2722  	// Copy curvalues stored in session to this proc.
  2723  	// Deep copy the map, takes some memory.
  2724  	ses.CopySeqToProc(proc)
  2725  	if ses.GetTenantInfo() != nil {
  2726  		proc.SessionInfo.Account = ses.GetTenantInfo().GetTenant()
  2727  		proc.SessionInfo.AccountId = ses.GetTenantInfo().GetTenantID()
  2728  		proc.SessionInfo.Role = ses.GetTenantInfo().GetDefaultRole()
  2729  		proc.SessionInfo.RoleId = ses.GetTenantInfo().GetDefaultRoleID()
  2730  		proc.SessionInfo.UserId = ses.GetTenantInfo().GetUserID()
  2731  
  2732  		if len(ses.GetTenantInfo().GetVersion()) != 0 {
  2733  			proc.SessionInfo.Version = ses.GetTenantInfo().GetVersion()
  2734  		}
  2735  		userNameOnly = ses.GetTenantInfo().GetUser()
  2736  	} else {
  2737  		var accountId uint32
  2738  		accountId, retErr = defines.GetAccountId(execCtx.reqCtx)
  2739  		if retErr != nil {
  2740  			return retErr
  2741  		}
  2742  		proc.SessionInfo.AccountId = accountId
  2743  		proc.SessionInfo.UserId = defines.GetUserId(execCtx.reqCtx)
  2744  		proc.SessionInfo.RoleId = defines.GetRoleId(execCtx.reqCtx)
  2745  	}
  2746  	var span trace.Span
  2747  	execCtx.reqCtx, span = trace.Start(execCtx.reqCtx, "doComQuery",
  2748  		trace.WithKind(trace.SpanKindStatement))
  2749  	defer span.End()
  2750  
  2751  	proc.SessionInfo.User = userNameOnly
  2752  	proc.SessionInfo.QueryId = ses.getQueryId(input.isInternal())
  2753  
  2754  	statsInfo := statistic.StatsInfo{ParseStartTime: beginInstant}
  2755  	execCtx.reqCtx = statistic.ContextWithStatsInfo(execCtx.reqCtx, &statsInfo)
  2756  	execCtx.input = input
  2757  
  2758  	cws, err := GetComputationWrapper(execCtx, ses.GetDatabaseName(),
  2759  		ses.GetUserName(),
  2760  		getGlobalPu().StorageEngine,
  2761  		proc, ses)
  2762  
  2763  	ParseDuration := time.Since(beginInstant)
  2764  
  2765  	if err != nil {
  2766  		statsInfo.ParseDuration = ParseDuration
  2767  		var err2 error
  2768  		execCtx.reqCtx, err2 = RecordParseErrorStatement(execCtx.reqCtx, ses, proc, beginInstant, parsers.HandleSqlForRecord(input.getSql()), input.getSqlSourceTypes(), err)
  2769  		if err2 != nil {
  2770  			return err2
  2771  		}
  2772  		retErr = err
  2773  		if _, ok := err.(*moerr.Error); !ok {
  2774  			retErr = moerr.NewParseError(execCtx.reqCtx, err.Error())
  2775  		}
  2776  		logStatementStringStatus(execCtx.reqCtx, ses, input.getSql(), fail, retErr)
  2777  		return retErr
  2778  	}
  2779  
  2780  	singleStatement := len(cws) == 1
  2781  	if ses.GetCmd() == COM_STMT_PREPARE && !singleStatement {
  2782  		return moerr.NewNotSupported(execCtx.reqCtx, "prepare multi statements")
  2783  	}
  2784  
  2785  	defer func() {
  2786  		ses.SetMysqlResultSet(nil)
  2787  	}()
  2788  
  2789  	canCache := true
  2790  	Cached := false
  2791  	defer func() {
  2792  		execCtx.stmt = nil
  2793  		execCtx.cw = nil
  2794  		execCtx.cws = nil
  2795  		if !Cached {
  2796  			for i := 0; i < len(cws); i++ {
  2797  				cws[i].Free()
  2798  			}
  2799  		}
  2800  	}()
  2801  	sqlRecord := parsers.HandleSqlForRecord(input.getSql())
  2802  
  2803  	for i, cw := range cws {
  2804  		if cwft, ok := cw.(*TxnComputationWrapper); ok {
  2805  			if cwft.stmt.GetQueryType() == tree.QueryTypeDDL || cwft.stmt.GetQueryType() == tree.QueryTypeDCL ||
  2806  				cwft.stmt.GetQueryType() == tree.QueryTypeOth ||
  2807  				cwft.stmt.GetQueryType() == tree.QueryTypeTCL {
  2808  				if _, ok := cwft.stmt.(*tree.SetVar); !ok {
  2809  					ses.cleanCache()
  2810  				}
  2811  				canCache = false
  2812  			}
  2813  		}
  2814  
  2815  		ses.SetMysqlResultSet(&MysqlResultSet{})
  2816  		ses.sentRows.Store(int64(0))
  2817  		ses.writeCsvBytes.Store(int64(0))
  2818  		proto.ResetStatistics() // move from getDataFromPipeline, for record column fields' data
  2819  		stmt := cw.GetAst()
  2820  		sqlType := input.getSqlSourceType(i)
  2821  		var err2 error
  2822  		execCtx.reqCtx, err2 = RecordStatement(execCtx.reqCtx, ses, proc, cw, beginInstant, sqlRecord[i], sqlType, singleStatement)
  2823  		if err2 != nil {
  2824  			return err2
  2825  		}
  2826  
  2827  		statsInfo.Reset()
  2828  		//average parse duration
  2829  		statsInfo.ParseDuration = time.Duration(ParseDuration.Nanoseconds() / int64(len(cws)))
  2830  
  2831  		tenant := ses.GetTenantNameWithStmt(stmt)
  2832  		//skip PREPARE statement here
  2833  		if ses.GetTenantInfo() != nil && !IsPrepareStatement(stmt) {
  2834  			err = authenticateUserCanExecuteStatement(execCtx.reqCtx, ses, stmt)
  2835  			if err != nil {
  2836  				logStatementStatus(execCtx.reqCtx, ses, stmt, fail, err)
  2837  				return err
  2838  			}
  2839  		}
  2840  
  2841  		/*
  2842  				if it is in an active or multi-statement transaction, we check the type of the statement.
  2843  				Then we decide that if we can execute the statement.
  2844  
  2845  			If we check the active transaction, it will generate the case below.
  2846  			case:
  2847  			set autocommit = 0;  <- no active transaction
  2848  			                     <- no active transaction
  2849  			drop table test1;    <- no active transaction, no error
  2850  			                     <- has active transaction
  2851  			drop table test1;    <- has active transaction, error
  2852  			                     <- has active transaction
  2853  		*/
  2854  		if ses.GetTxnHandler().InActiveTxn() {
  2855  			err = canExecuteStatementInUncommittedTransaction(execCtx.reqCtx, ses, stmt)
  2856  			if err != nil {
  2857  				logStatementStatus(execCtx.reqCtx, ses, stmt, fail, err)
  2858  				return err
  2859  			}
  2860  		}
  2861  
  2862  		// update UnixTime for new query, which is used for now() / CURRENT_TIMESTAMP
  2863  		proc.UnixTime = time.Now().UnixNano()
  2864  		if ses.proc != nil {
  2865  			ses.proc.UnixTime = proc.UnixTime
  2866  		}
  2867  		execCtx.stmt = stmt
  2868  		execCtx.isLastStmt = i >= len(cws)-1
  2869  		execCtx.tenant = tenant
  2870  		execCtx.userName = userNameOnly
  2871  		execCtx.sqlOfStmt = sqlRecord[i]
  2872  		execCtx.cw = cw
  2873  		execCtx.proc = proc
  2874  		execCtx.proto = proto
  2875  		execCtx.ses = ses
  2876  		execCtx.cws = cws
  2877  		execCtx.input = input
  2878  
  2879  		err = executeStmtWithResponse(ses, execCtx)
  2880  		if err != nil {
  2881  			return err
  2882  		}
  2883  
  2884  	} // end of for
  2885  
  2886  	if canCache && !ses.isCached(input.getSql()) {
  2887  		plans := make([]*plan.Plan, len(cws))
  2888  		stmts := make([]tree.Statement, len(cws))
  2889  		for i, cw := range cws {
  2890  			if cwft, ok := cw.(*TxnComputationWrapper); ok {
  2891  				if checkNodeCanCache(cwft.plan) {
  2892  					plans[i] = cwft.plan
  2893  					stmts[i] = cwft.stmt
  2894  				} else {
  2895  					return nil
  2896  				}
  2897  			}
  2898  			cw.Clear()
  2899  		}
  2900  		Cached = true
  2901  		ses.cachePlan(input.getSql(), stmts, plans)
  2902  	}
  2903  
  2904  	return nil
  2905  }
  2906  
  2907  func checkNodeCanCache(p *plan2.Plan) bool {
  2908  	if p == nil {
  2909  		return true
  2910  	}
  2911  	if q, ok := p.Plan.(*plan2.Plan_Query); ok {
  2912  		for _, node := range q.Query.Nodes {
  2913  			if node.NotCacheable {
  2914  				return false
  2915  			}
  2916  			if node.ObjRef != nil && len(node.ObjRef.SubscriptionName) > 0 {
  2917  				return false
  2918  			}
  2919  		}
  2920  	}
  2921  	return true
  2922  }
  2923  
  2924  // ExecRequest the server execute the commands from the client following the mysql's routine
  2925  func ExecRequest(ses *Session, execCtx *ExecCtx, req *Request) (resp *Response, err error) {
  2926  	defer func() {
  2927  		if e := recover(); e != nil {
  2928  			moe, ok := e.(*moerr.Error)
  2929  			if !ok {
  2930  				err = moerr.ConvertPanicError(execCtx.reqCtx, e)
  2931  				resp = NewGeneralErrorResponse(COM_QUERY, ses.txnHandler.GetServerStatus(), err)
  2932  			} else {
  2933  				resp = NewGeneralErrorResponse(COM_QUERY, ses.txnHandler.GetServerStatus(), moe)
  2934  			}
  2935  		}
  2936  	}()
  2937  
  2938  	var span trace.Span
  2939  	execCtx.reqCtx, span = trace.Start(execCtx.reqCtx, "ExecRequest",
  2940  		trace.WithKind(trace.SpanKindStatement))
  2941  	defer span.End()
  2942  
  2943  	var sql string
  2944  	logDebugf(ses.GetDebugString(), "cmd %v", req.GetCmd())
  2945  	ses.SetCmd(req.GetCmd())
  2946  	switch req.GetCmd() {
  2947  	case COM_QUIT:
  2948  		return resp, moerr.GetMysqlClientQuit()
  2949  	case COM_QUERY:
  2950  		var query = string(req.GetData().([]byte))
  2951  		ses.addSqlCount(1)
  2952  		logDebug(ses, ses.GetDebugString(), "query trace", logutil.ConnectionIdField(ses.GetConnectionID()), logutil.QueryField(SubStringFromBegin(query, int(getGlobalPu().SV.LengthOfQueryPrinted))))
  2953  		err = doComQuery(ses, execCtx, &UserInput{sql: query})
  2954  		if err != nil {
  2955  			resp = NewGeneralErrorResponse(COM_QUERY, ses.GetTxnHandler().GetServerStatus(), err)
  2956  		}
  2957  		return resp, nil
  2958  	case COM_INIT_DB:
  2959  		var dbname = string(req.GetData().([]byte))
  2960  		ses.addSqlCount(1)
  2961  		query := "use `" + dbname + "`"
  2962  		err = doComQuery(ses, execCtx, &UserInput{sql: query})
  2963  		if err != nil {
  2964  			resp = NewGeneralErrorResponse(COM_INIT_DB, ses.GetTxnHandler().GetServerStatus(), err)
  2965  		}
  2966  
  2967  		return resp, nil
  2968  	case COM_FIELD_LIST:
  2969  		var payload = string(req.GetData().([]byte))
  2970  		ses.addSqlCount(1)
  2971  		query := makeCmdFieldListSql(payload)
  2972  		err = doComQuery(ses, execCtx, &UserInput{sql: query})
  2973  		if err != nil {
  2974  			resp = NewGeneralErrorResponse(COM_FIELD_LIST, ses.GetTxnHandler().GetServerStatus(), err)
  2975  		}
  2976  
  2977  		return resp, nil
  2978  	case COM_PING:
  2979  		resp = NewGeneralOkResponse(COM_PING, ses.GetTxnHandler().GetServerStatus())
  2980  
  2981  		return resp, nil
  2982  
  2983  	case COM_STMT_PREPARE:
  2984  		ses.SetCmd(COM_STMT_PREPARE)
  2985  		sql = string(req.GetData().([]byte))
  2986  		ses.addSqlCount(1)
  2987  
  2988  		// rewrite to "Prepare stmt_name from 'xxx'"
  2989  		newLastStmtID := ses.GenNewStmtId()
  2990  		newStmtName := getPrepareStmtName(newLastStmtID)
  2991  		sql = fmt.Sprintf("prepare %s from %s", newStmtName, sql)
  2992  		logDebug(ses, ses.GetDebugString(), "query trace", logutil.ConnectionIdField(ses.GetConnectionID()), logutil.QueryField(sql))
  2993  
  2994  		err = doComQuery(ses, execCtx, &UserInput{sql: sql})
  2995  		if err != nil {
  2996  			resp = NewGeneralErrorResponse(COM_STMT_PREPARE, ses.GetTxnHandler().GetServerStatus(), err)
  2997  		}
  2998  		return resp, nil
  2999  
  3000  	case COM_STMT_EXECUTE:
  3001  		ses.SetCmd(COM_STMT_EXECUTE)
  3002  		data := req.GetData().([]byte)
  3003  		var prepareStmt *PrepareStmt
  3004  		sql, prepareStmt, err = parseStmtExecute(execCtx.reqCtx, ses, data)
  3005  		if err != nil {
  3006  			return NewGeneralErrorResponse(COM_STMT_EXECUTE, ses.GetTxnHandler().GetServerStatus(), err), nil
  3007  		}
  3008  		err = doComQuery(ses, execCtx, &UserInput{sql: sql})
  3009  		if err != nil {
  3010  			resp = NewGeneralErrorResponse(COM_STMT_EXECUTE, ses.GetTxnHandler().GetServerStatus(), err)
  3011  		}
  3012  		if prepareStmt.params != nil {
  3013  			prepareStmt.params.GetNulls().Reset()
  3014  			for k := range prepareStmt.getFromSendLongData {
  3015  				delete(prepareStmt.getFromSendLongData, k)
  3016  			}
  3017  		}
  3018  		return resp, nil
  3019  
  3020  	case COM_STMT_SEND_LONG_DATA:
  3021  		ses.SetCmd(COM_STMT_SEND_LONG_DATA)
  3022  		data := req.GetData().([]byte)
  3023  		err = parseStmtSendLongData(execCtx.reqCtx, ses, data)
  3024  		if err != nil {
  3025  			resp = NewGeneralErrorResponse(COM_STMT_SEND_LONG_DATA, ses.GetTxnHandler().GetServerStatus(), err)
  3026  			return resp, nil
  3027  		}
  3028  		return nil, nil
  3029  
  3030  	case COM_STMT_CLOSE:
  3031  		data := req.GetData().([]byte)
  3032  
  3033  		// rewrite to "deallocate Prepare stmt_name"
  3034  		stmtID := binary.LittleEndian.Uint32(data[0:4])
  3035  		stmtName := getPrepareStmtName(stmtID)
  3036  		sql = fmt.Sprintf("deallocate prepare %s", stmtName)
  3037  		logDebug(ses, ses.GetDebugString(), "query trace", logutil.ConnectionIdField(ses.GetConnectionID()), logutil.QueryField(sql))
  3038  
  3039  		err = doComQuery(ses, execCtx, &UserInput{sql: sql})
  3040  		if err != nil {
  3041  			resp = NewGeneralErrorResponse(COM_STMT_CLOSE, ses.GetTxnHandler().GetServerStatus(), err)
  3042  		}
  3043  		return resp, nil
  3044  
  3045  	case COM_STMT_RESET:
  3046  		data := req.GetData().([]byte)
  3047  
  3048  		//Payload of COM_STMT_RESET
  3049  		stmtID := binary.LittleEndian.Uint32(data[0:4])
  3050  		stmtName := getPrepareStmtName(stmtID)
  3051  		sql = fmt.Sprintf("reset prepare %s", stmtName)
  3052  		logDebug(ses, ses.GetDebugString(), "query trace", logutil.ConnectionIdField(ses.GetConnectionID()), logutil.QueryField(sql))
  3053  		err = doComQuery(ses, execCtx, &UserInput{sql: sql})
  3054  		if err != nil {
  3055  			resp = NewGeneralErrorResponse(COM_STMT_RESET, ses.GetTxnHandler().GetServerStatus(), err)
  3056  		}
  3057  		return resp, nil
  3058  
  3059  	case COM_SET_OPTION:
  3060  		data := req.GetData().([]byte)
  3061  		err := handleSetOption(ses, execCtx, data)
  3062  		if err != nil {
  3063  			resp = NewGeneralErrorResponse(COM_SET_OPTION, ses.GetTxnHandler().GetServerStatus(), err)
  3064  		}
  3065  		return NewGeneralOkResponse(COM_SET_OPTION, ses.GetTxnHandler().GetServerStatus()), nil
  3066  
  3067  	default:
  3068  		resp = NewGeneralErrorResponse(req.GetCmd(), ses.GetTxnHandler().GetServerStatus(), moerr.NewInternalError(execCtx.reqCtx, "unsupported command. 0x%x", req.GetCmd()))
  3069  	}
  3070  	return resp, nil
  3071  }
  3072  
  3073  func parseStmtExecute(reqCtx context.Context, ses *Session, data []byte) (string, *PrepareStmt, error) {
  3074  	// see https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_com_stmt_execute.html
  3075  	pos := 0
  3076  	if len(data) < 4 {
  3077  		return "", nil, moerr.NewInvalidInput(reqCtx, "sql command contains malformed packet")
  3078  	}
  3079  	stmtID := binary.LittleEndian.Uint32(data[0:4])
  3080  	pos += 4
  3081  
  3082  	stmtName := fmt.Sprintf("%s_%d", prefixPrepareStmtName, stmtID)
  3083  	preStmt, err := ses.GetPrepareStmt(reqCtx, stmtName)
  3084  	if err != nil {
  3085  		return "", nil, err
  3086  	}
  3087  
  3088  	sql := fmt.Sprintf("execute %s", stmtName)
  3089  	logDebug(ses, ses.GetDebugString(), "query trace", logutil.ConnectionIdField(ses.GetConnectionID()), logutil.QueryField(sql))
  3090  	err = ses.GetMysqlProtocol().ParseExecuteData(reqCtx, ses.GetTxnCompileCtx().GetProcess(), preStmt, data, pos)
  3091  	if err != nil {
  3092  		return "", nil, err
  3093  	}
  3094  	return sql, preStmt, nil
  3095  }
  3096  
  3097  func parseStmtSendLongData(reqCtx context.Context, ses *Session, data []byte) error {
  3098  	// see https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_com_stmt_send_long_data.html
  3099  	pos := 0
  3100  	if len(data) < 4 {
  3101  		return moerr.NewInvalidInput(reqCtx, "sql command contains malformed packet")
  3102  	}
  3103  	stmtID := binary.LittleEndian.Uint32(data[0:4])
  3104  	pos += 4
  3105  
  3106  	stmtName := fmt.Sprintf("%s_%d", prefixPrepareStmtName, stmtID)
  3107  	preStmt, err := ses.GetPrepareStmt(reqCtx, stmtName)
  3108  	if err != nil {
  3109  		return err
  3110  	}
  3111  
  3112  	sql := fmt.Sprintf("send long data for stmt %s", stmtName)
  3113  	logDebug(ses, ses.GetDebugString(), "query trace", logutil.ConnectionIdField(ses.GetConnectionID()), logutil.QueryField(sql))
  3114  
  3115  	err = ses.GetMysqlProtocol().ParseSendLongData(reqCtx, ses.GetTxnCompileCtx().GetProcess(), preStmt, data, pos)
  3116  	if err != nil {
  3117  		return err
  3118  	}
  3119  	return nil
  3120  }
  3121  
  3122  /*
  3123  convert the type in computation engine to the type in mysql.
  3124  */
  3125  func convertEngineTypeToMysqlType(ctx context.Context, engineType types.T, col *MysqlColumn) error {
  3126  	switch engineType {
  3127  	case types.T_any:
  3128  		col.SetColumnType(defines.MYSQL_TYPE_NULL)
  3129  	case types.T_json:
  3130  		col.SetColumnType(defines.MYSQL_TYPE_JSON)
  3131  	case types.T_bool:
  3132  		col.SetColumnType(defines.MYSQL_TYPE_BOOL)
  3133  	case types.T_bit:
  3134  		col.SetColumnType(defines.MYSQL_TYPE_BIT)
  3135  		col.SetSigned(false)
  3136  	case types.T_int8:
  3137  		col.SetColumnType(defines.MYSQL_TYPE_TINY)
  3138  	case types.T_uint8:
  3139  		col.SetColumnType(defines.MYSQL_TYPE_TINY)
  3140  		col.SetSigned(false)
  3141  	case types.T_int16:
  3142  		col.SetColumnType(defines.MYSQL_TYPE_SHORT)
  3143  	case types.T_uint16:
  3144  		col.SetColumnType(defines.MYSQL_TYPE_SHORT)
  3145  		col.SetSigned(false)
  3146  	case types.T_int32:
  3147  		col.SetColumnType(defines.MYSQL_TYPE_LONG)
  3148  	case types.T_uint32:
  3149  		col.SetColumnType(defines.MYSQL_TYPE_LONG)
  3150  		col.SetSigned(false)
  3151  	case types.T_int64:
  3152  		col.SetColumnType(defines.MYSQL_TYPE_LONGLONG)
  3153  	case types.T_uint64:
  3154  		col.SetColumnType(defines.MYSQL_TYPE_LONGLONG)
  3155  		col.SetSigned(false)
  3156  	case types.T_float32:
  3157  		col.SetColumnType(defines.MYSQL_TYPE_FLOAT)
  3158  	case types.T_float64:
  3159  		col.SetColumnType(defines.MYSQL_TYPE_DOUBLE)
  3160  	case types.T_char:
  3161  		col.SetColumnType(defines.MYSQL_TYPE_STRING)
  3162  	case types.T_varchar:
  3163  		col.SetColumnType(defines.MYSQL_TYPE_VAR_STRING)
  3164  	case types.T_array_float32, types.T_array_float64:
  3165  		col.SetColumnType(defines.MYSQL_TYPE_VARCHAR)
  3166  	case types.T_binary:
  3167  		col.SetColumnType(defines.MYSQL_TYPE_VARCHAR)
  3168  	case types.T_varbinary:
  3169  		col.SetColumnType(defines.MYSQL_TYPE_VARCHAR)
  3170  	case types.T_date:
  3171  		col.SetColumnType(defines.MYSQL_TYPE_DATE)
  3172  	case types.T_datetime:
  3173  		col.SetColumnType(defines.MYSQL_TYPE_DATETIME)
  3174  	case types.T_time:
  3175  		col.SetColumnType(defines.MYSQL_TYPE_TIME)
  3176  	case types.T_timestamp:
  3177  		col.SetColumnType(defines.MYSQL_TYPE_TIMESTAMP)
  3178  	case types.T_decimal64:
  3179  		col.SetColumnType(defines.MYSQL_TYPE_DECIMAL)
  3180  	case types.T_decimal128:
  3181  		col.SetColumnType(defines.MYSQL_TYPE_DECIMAL)
  3182  	case types.T_blob:
  3183  		col.SetColumnType(defines.MYSQL_TYPE_BLOB)
  3184  	case types.T_text:
  3185  		col.SetColumnType(defines.MYSQL_TYPE_TEXT)
  3186  	case types.T_uuid:
  3187  		col.SetColumnType(defines.MYSQL_TYPE_UUID)
  3188  	case types.T_TS:
  3189  		col.SetColumnType(defines.MYSQL_TYPE_VARCHAR)
  3190  	case types.T_Blockid:
  3191  		col.SetColumnType(defines.MYSQL_TYPE_VARCHAR)
  3192  	case types.T_enum:
  3193  		col.SetColumnType(defines.MYSQL_TYPE_VARCHAR)
  3194  	default:
  3195  		return moerr.NewInternalError(ctx, "RunWhileSend : unsupported type %d", engineType)
  3196  	}
  3197  	return nil
  3198  }
  3199  
  3200  func convertMysqlTextTypeToBlobType(col *MysqlColumn) {
  3201  	if col.ColumnType() == defines.MYSQL_TYPE_TEXT {
  3202  		col.SetColumnType(defines.MYSQL_TYPE_BLOB)
  3203  	}
  3204  }
  3205  
  3206  // build plan json when marhal plan error
  3207  func buildErrorJsonPlan(buffer *bytes.Buffer, uuid uuid.UUID, errcode uint16, msg string) []byte {
  3208  	var bytes [36]byte
  3209  	util.EncodeUUIDHex(bytes[:], uuid[:])
  3210  	explainData := explain.ExplainData{
  3211  		Code:    errcode,
  3212  		Message: msg,
  3213  		Uuid:    util.UnsafeBytesToString(bytes[:]),
  3214  	}
  3215  	encoder := json.NewEncoder(buffer)
  3216  	encoder.SetEscapeHTML(false)
  3217  	encoder.Encode(explainData)
  3218  	return buffer.Bytes()
  3219  }
  3220  
  3221  type jsonPlanHandler struct {
  3222  	jsonBytes  []byte
  3223  	statsBytes statistic.StatsArray
  3224  	stats      motrace.Statistic
  3225  	buffer     *bytes.Buffer
  3226  }
  3227  
  3228  func NewJsonPlanHandler(ctx context.Context, stmt *motrace.StatementInfo, plan *plan2.Plan, opts ...marshalPlanOptions) *jsonPlanHandler {
  3229  	h := NewMarshalPlanHandler(ctx, stmt, plan, opts...)
  3230  	jsonBytes := h.Marshal(ctx)
  3231  	statsBytes, stats := h.Stats(ctx)
  3232  	return &jsonPlanHandler{
  3233  		jsonBytes:  jsonBytes,
  3234  		statsBytes: statsBytes,
  3235  		stats:      stats,
  3236  		buffer:     h.handoverBuffer(),
  3237  	}
  3238  }
  3239  
  3240  func (h *jsonPlanHandler) Stats(ctx context.Context) (statistic.StatsArray, motrace.Statistic) {
  3241  	return h.statsBytes, h.stats
  3242  }
  3243  
  3244  func (h *jsonPlanHandler) Marshal(ctx context.Context) []byte {
  3245  	return h.jsonBytes
  3246  }
  3247  
  3248  func (h *jsonPlanHandler) Free() {
  3249  	if h.buffer != nil {
  3250  		releaseMarshalPlanBufferPool(h.buffer)
  3251  		h.buffer = nil
  3252  		h.jsonBytes = nil
  3253  	}
  3254  }
  3255  
  3256  type marshalPlanConfig struct {
  3257  	waitActiveCost time.Duration
  3258  }
  3259  
  3260  type marshalPlanOptions func(*marshalPlanConfig)
  3261  
  3262  func WithWaitActiveCost(cost time.Duration) marshalPlanOptions {
  3263  	return func(h *marshalPlanConfig) {
  3264  		h.waitActiveCost = cost
  3265  	}
  3266  }
  3267  
  3268  type marshalPlanHandler struct {
  3269  	query       *plan.Query
  3270  	marshalPlan *explain.ExplainData
  3271  	stmt        *motrace.StatementInfo
  3272  	uuid        uuid.UUID
  3273  	buffer      *bytes.Buffer
  3274  
  3275  	marshalPlanConfig
  3276  }
  3277  
  3278  func NewMarshalPlanHandler(ctx context.Context, stmt *motrace.StatementInfo, plan *plan2.Plan, opts ...marshalPlanOptions) *marshalPlanHandler {
  3279  	// TODO: need mem improvement
  3280  	uuid := uuid.UUID(stmt.StatementID)
  3281  	stmt.MarkResponseAt()
  3282  	if plan == nil || plan.GetQuery() == nil {
  3283  		return &marshalPlanHandler{
  3284  			query:       nil,
  3285  			marshalPlan: nil,
  3286  			stmt:        stmt,
  3287  			uuid:        uuid,
  3288  			buffer:      nil,
  3289  		}
  3290  	}
  3291  	query := plan.GetQuery()
  3292  	h := &marshalPlanHandler{
  3293  		query:  query,
  3294  		stmt:   stmt,
  3295  		uuid:   uuid,
  3296  		buffer: nil,
  3297  	}
  3298  	// END> new marshalPlanHandler
  3299  
  3300  	// SET options
  3301  	for _, opt := range opts {
  3302  		opt(&h.marshalPlanConfig)
  3303  	}
  3304  
  3305  	if h.needMarshalPlan() {
  3306  		h.marshalPlan = explain.BuildJsonPlan(ctx, h.uuid, &explain.MarshalPlanOptions, h.query)
  3307  		h.marshalPlan.NewPlanStats.SetWaitActiveCost(h.waitActiveCost)
  3308  	}
  3309  	return h
  3310  }
  3311  
  3312  // needMarshalPlan return true if statement.duration - waitActive > longQueryTime && NOT mo_logger query
  3313  // check longQueryTime, need after StatementInfo.MarkResponseAt
  3314  // MoLogger NOT record ExecPlan
  3315  func (h *marshalPlanHandler) needMarshalPlan() bool {
  3316  	return (h.stmt.Duration-h.waitActiveCost) > motrace.GetLongQueryTime() &&
  3317  		!h.stmt.IsMoLogger()
  3318  }
  3319  
  3320  func (h *marshalPlanHandler) Free() {
  3321  	h.stmt = nil
  3322  	if h.buffer != nil {
  3323  		releaseMarshalPlanBufferPool(h.buffer)
  3324  		h.buffer = nil
  3325  	}
  3326  }
  3327  
  3328  func (h *marshalPlanHandler) handoverBuffer() *bytes.Buffer {
  3329  	b := h.buffer
  3330  	h.buffer = nil
  3331  	return b
  3332  }
  3333  
  3334  var marshalPlanBufferPool = sync.Pool{New: func() any {
  3335  	return bytes.NewBuffer(make([]byte, 0, 8192))
  3336  }}
  3337  
  3338  // get buffer from marshalPlanBufferPool
  3339  func getMarshalPlanBufferPool() *bytes.Buffer {
  3340  	return marshalPlanBufferPool.Get().(*bytes.Buffer)
  3341  }
  3342  
  3343  func releaseMarshalPlanBufferPool(b *bytes.Buffer) {
  3344  	marshalPlanBufferPool.Put(b)
  3345  }
  3346  
  3347  // allocBufferIfNeeded should call just right before needed.
  3348  // It will reuse buffer from pool if possible.
  3349  func (h *marshalPlanHandler) allocBufferIfNeeded() {
  3350  	if h.buffer == nil {
  3351  		h.buffer = getMarshalPlanBufferPool()
  3352  	}
  3353  }
  3354  
  3355  func (h *marshalPlanHandler) Marshal(ctx context.Context) (jsonBytes []byte) {
  3356  	var err error
  3357  	if h.marshalPlan != nil {
  3358  		h.allocBufferIfNeeded()
  3359  		h.buffer.Reset()
  3360  		var jsonBytesLen = 0
  3361  		// XXX, `buffer` can be used repeatedly as a global variable in the future
  3362  		// Provide a relatively balanced initial capacity [8192] for byte slice to prevent multiple memory requests
  3363  		encoder := json.NewEncoder(h.buffer)
  3364  		encoder.SetEscapeHTML(false)
  3365  		err = encoder.Encode(h.marshalPlan)
  3366  		if err != nil {
  3367  			moError := moerr.NewInternalError(ctx, "serialize plan to json error: %s", err.Error())
  3368  			h.buffer.Reset()
  3369  			jsonBytes = buildErrorJsonPlan(h.buffer, h.uuid, moError.ErrorCode(), moError.Error())
  3370  		} else {
  3371  			jsonBytesLen = h.buffer.Len()
  3372  		}
  3373  		// BG: bytes.Buffer maintain buf []byte.
  3374  		// if buf[off:] not enough but len(buf) is enough place, then it will reset off = 0.
  3375  		// So, in here, we need call Next(...) after all data has been written
  3376  		if jsonBytesLen > 0 {
  3377  			jsonBytes = h.buffer.Next(jsonBytesLen)
  3378  		}
  3379  	} else if h.query != nil {
  3380  		// DO NOT use h.buffer
  3381  		return sqlQueryIgnoreExecPlan
  3382  	} else {
  3383  		// DO NOT use h.buffer
  3384  		return sqlQueryNoRecordExecPlan
  3385  	}
  3386  	return
  3387  }
  3388  
  3389  var sqlQueryIgnoreExecPlan = []byte(`{}`)
  3390  var sqlQueryNoRecordExecPlan = []byte(`{"code":200,"message":"sql query no record execution plan"}`)
  3391  
  3392  func (h *marshalPlanHandler) Stats(ctx context.Context) (statsByte statistic.StatsArray, stats motrace.Statistic) {
  3393  	if h.query != nil {
  3394  		options := &explain.MarshalPlanOptions
  3395  		statsByte.Reset()
  3396  		for _, node := range h.query.Nodes {
  3397  			// part 1: for statistic.StatsArray
  3398  			s := explain.GetStatistic4Trace(ctx, node, options)
  3399  			statsByte.Add(&s)
  3400  			// part 2: for motrace.Statistic
  3401  			if node.NodeType == plan.Node_TABLE_SCAN || node.NodeType == plan.Node_EXTERNAL_SCAN {
  3402  				rows, bytes := explain.GetInputRowsAndInputSize(ctx, node, options)
  3403  				stats.RowsRead += rows
  3404  				stats.BytesScan += bytes
  3405  			}
  3406  		}
  3407  	} else {
  3408  		statsByte = statistic.DefaultStatsArray
  3409  	}
  3410  	statsInfo := statistic.StatsInfoFromContext(ctx)
  3411  	if statsInfo != nil {
  3412  		val := int64(statsByte.GetTimeConsumed()) +
  3413  			int64(statsInfo.ParseDuration+
  3414  				statsInfo.CompileDuration+
  3415  				statsInfo.PlanDuration) - (statsInfo.IOAccessTimeConsumption + statsInfo.IOMergerTimeConsumption())
  3416  		if val < 0 {
  3417  			logutil.Warnf(" negative cpu (%s) + statsInfo(%d + %d + %d - %d - %d) = %d",
  3418  				uuid.UUID(h.stmt.StatementID).String(),
  3419  				statsInfo.ParseDuration,
  3420  				statsInfo.CompileDuration,
  3421  				statsInfo.PlanDuration,
  3422  				statsInfo.IOAccessTimeConsumption,
  3423  				statsInfo.IOMergerTimeConsumption(),
  3424  				val)
  3425  			v2.GetTraceNegativeCUCounter("cpu").Inc()
  3426  		} else {
  3427  			statsByte.WithTimeConsumed(float64(val))
  3428  		}
  3429  	}
  3430  
  3431  	return
  3432  }
  3433  
  3434  func handleSetOption(ses *Session, execCtx *ExecCtx, data []byte) (err error) {
  3435  	if len(data) < 2 {
  3436  		return moerr.NewInternalError(execCtx.reqCtx, "invalid cmd_set_option data length")
  3437  	}
  3438  	cap := ses.GetMysqlProtocol().GetCapability()
  3439  	switch binary.LittleEndian.Uint16(data[:2]) {
  3440  	case 0:
  3441  		// MO do not support CLIENT_MULTI_STATEMENTS in prepare, so do nothing here(Like MySQL)
  3442  		// cap |= CLIENT_MULTI_STATEMENTS
  3443  		// GetSession().GetMysqlProtocol().SetCapability(cap)
  3444  
  3445  	case 1:
  3446  		cap &^= CLIENT_MULTI_STATEMENTS
  3447  		ses.GetMysqlProtocol().SetCapability(cap)
  3448  
  3449  	default:
  3450  		return moerr.NewInternalError(execCtx.reqCtx, "invalid cmd_set_option data")
  3451  	}
  3452  
  3453  	return nil
  3454  }
  3455  
  3456  func handleExecUpgrade(ses *Session, execCtx *ExecCtx, st *tree.UpgradeStatement) error {
  3457  	retryCount := st.Retry
  3458  	if st.Retry <= 0 {
  3459  		retryCount = 1
  3460  	}
  3461  	err := ses.UpgradeTenant(execCtx.reqCtx, st.Target.AccountName, uint32(retryCount), st.Target.IsALLAccount)
  3462  	if err != nil {
  3463  		return err
  3464  	}
  3465  
  3466  	return nil
  3467  }