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

     1  // Copyright 2021 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package frontend
    16  
    17  import (
    18  	"bytes"
    19  	"context"
    20  	"fmt"
    21  	"os"
    22  	"runtime"
    23  	"strconv"
    24  	"sync/atomic"
    25  	"time"
    26  
    27  	"go.uber.org/zap"
    28  
    29  	"path/filepath"
    30  	"strings"
    31  
    32  	"github.com/BurntSushi/toml"
    33  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    34  	"github.com/matrixorigin/matrixone/pkg/common/mpool"
    35  	"github.com/matrixorigin/matrixone/pkg/container/batch"
    36  	"github.com/matrixorigin/matrixone/pkg/container/nulls"
    37  	"github.com/matrixorigin/matrixone/pkg/container/types"
    38  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    39  	"github.com/matrixorigin/matrixone/pkg/sql/colexec"
    40  	plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan"
    41  	dumpUtils "github.com/matrixorigin/matrixone/pkg/vectorize/dump"
    42  
    43  	mo_config "github.com/matrixorigin/matrixone/pkg/config"
    44  	"github.com/matrixorigin/matrixone/pkg/logutil"
    45  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect"
    46  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
    47  	"github.com/matrixorigin/matrixone/pkg/util/trace"
    48  	"github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace"
    49  	"github.com/matrixorigin/matrixone/pkg/vm/engine"
    50  )
    51  
    52  type CloseFlag struct {
    53  	//closed flag
    54  	closed uint32
    55  }
    56  
    57  // 1 for closed
    58  // 0 for others
    59  func (cf *CloseFlag) setClosed(value uint32) {
    60  	atomic.StoreUint32(&cf.closed, value)
    61  }
    62  
    63  func (cf *CloseFlag) Open() {
    64  	cf.setClosed(0)
    65  }
    66  
    67  func (cf *CloseFlag) Close() {
    68  	cf.setClosed(1)
    69  }
    70  
    71  func (cf *CloseFlag) IsClosed() bool {
    72  	return atomic.LoadUint32(&cf.closed) != 0
    73  }
    74  
    75  func (cf *CloseFlag) IsOpened() bool {
    76  	return atomic.LoadUint32(&cf.closed) == 0
    77  }
    78  
    79  func Min(a int, b int) int {
    80  	if a < b {
    81  		return a
    82  	} else {
    83  		return b
    84  	}
    85  }
    86  
    87  func MinInt64(a int64, b int64) int64 {
    88  	if a < b {
    89  		return a
    90  	} else {
    91  		return b
    92  	}
    93  }
    94  
    95  func MinUint64(a uint64, b uint64) uint64 {
    96  	if a < b {
    97  		return a
    98  	} else {
    99  		return b
   100  	}
   101  }
   102  
   103  func Max(a int, b int) int {
   104  	if a < b {
   105  		return b
   106  	} else {
   107  		return a
   108  	}
   109  }
   110  
   111  func MaxInt64(a int64, b int64) int64 {
   112  	if a < b {
   113  		return b
   114  	} else {
   115  		return a
   116  	}
   117  }
   118  
   119  func MaxUint64(a uint64, b uint64) uint64 {
   120  	if a < b {
   121  		return b
   122  	} else {
   123  		return a
   124  	}
   125  }
   126  
   127  type Uint64List []uint64
   128  
   129  func (ul Uint64List) Len() int {
   130  	return len(ul)
   131  }
   132  
   133  func (ul Uint64List) Less(i, j int) bool {
   134  	return ul[i] < ul[j]
   135  }
   136  
   137  func (ul Uint64List) Swap(i, j int) {
   138  	ul[i], ul[j] = ul[j], ul[i]
   139  }
   140  
   141  // GetRoutineId gets the routine id
   142  func GetRoutineId() uint64 {
   143  	data := make([]byte, 64)
   144  	data = data[:runtime.Stack(data, false)]
   145  	data = bytes.TrimPrefix(data, []byte("goroutine "))
   146  	data = data[:bytes.IndexByte(data, ' ')]
   147  	id, _ := strconv.ParseUint(string(data), 10, 64)
   148  	return id
   149  }
   150  
   151  type DebugCounter struct {
   152  	length  int
   153  	counter []uint64
   154  	Cf      CloseFlag
   155  }
   156  
   157  func NewDebugCounter(l int) *DebugCounter {
   158  	return &DebugCounter{
   159  		length:  l,
   160  		counter: make([]uint64, l),
   161  	}
   162  }
   163  
   164  func (dc *DebugCounter) Add(i int, v uint64) {
   165  	atomic.AddUint64(&dc.counter[i], v)
   166  }
   167  
   168  func (dc *DebugCounter) Set(i int, v uint64) {
   169  	atomic.StoreUint64(&dc.counter[i], v)
   170  }
   171  
   172  func (dc *DebugCounter) Get(i int) uint64 {
   173  	return atomic.LoadUint64(&dc.counter[i])
   174  }
   175  
   176  func (dc *DebugCounter) Len() int {
   177  	return dc.length
   178  }
   179  
   180  func (dc *DebugCounter) DCRoutine() {
   181  	dc.Cf.Open()
   182  
   183  	for dc.Cf.IsOpened() {
   184  		for i := 0; i < dc.length; i++ {
   185  			if i != 0 && i%8 == 0 {
   186  				logutil.Infof("")
   187  			}
   188  			v := dc.Get(i)
   189  			logutil.Infof("[%4d %4d]", i, v)
   190  			dc.Set(i, 0)
   191  		}
   192  		logutil.Infof("")
   193  		time.Sleep(5 * time.Second)
   194  	}
   195  }
   196  
   197  const (
   198  	TIMEOUT_TYPE_SECOND int = iota
   199  	TIMEOUT_TYPE_MILLISECOND
   200  )
   201  
   202  type Timeout struct {
   203  	//last record of the time
   204  	lastTime atomic.Value //time.Time
   205  
   206  	//period
   207  	timeGap time.Duration
   208  
   209  	//auto update
   210  	autoUpdate bool
   211  }
   212  
   213  func NewTimeout(tg time.Duration, autoUpdateWhenChecked bool) *Timeout {
   214  	ret := &Timeout{
   215  		timeGap:    tg,
   216  		autoUpdate: autoUpdateWhenChecked,
   217  	}
   218  	ret.lastTime.Store(time.Now())
   219  	return ret
   220  }
   221  
   222  func (t *Timeout) UpdateTime(tn time.Time) {
   223  	t.lastTime.Store(tn)
   224  }
   225  
   226  /*
   227  ----------+---------+------------------+--------
   228  
   229  	lastTime     Now         lastTime + timeGap
   230  
   231  return true  :  is timeout. the lastTime has been updated.
   232  return false :  is not timeout. the lastTime has not been updated.
   233  */
   234  func (t *Timeout) isTimeout() bool {
   235  	if time.Since(t.lastTime.Load().(time.Time)) <= t.timeGap {
   236  		return false
   237  	}
   238  
   239  	if t.autoUpdate {
   240  		t.lastTime.Store(time.Now())
   241  	}
   242  	return true
   243  }
   244  
   245  /*
   246  length:
   247  -1, complete string.
   248  0, empty string
   249  >0 , length of characters at the header of the string.
   250  */
   251  func SubStringFromBegin(str string, length int) string {
   252  	if length == 0 || length < -1 {
   253  		return ""
   254  	}
   255  
   256  	if length == -1 {
   257  		return str
   258  	}
   259  
   260  	l := Min(len(str), length)
   261  	if l != len(str) {
   262  		return str[:l] + "..."
   263  	}
   264  	return str[:l]
   265  }
   266  
   267  /*
   268  path exists in the system
   269  return:
   270  true/false - exists or not.
   271  true/false - file or directory
   272  error
   273  */
   274  var PathExists = func(path string) (bool, bool, error) {
   275  	fi, err := os.Stat(path)
   276  	if err == nil {
   277  		return true, !fi.IsDir(), nil
   278  	}
   279  	if os.IsNotExist(err) {
   280  		return false, false, err
   281  	}
   282  
   283  	return false, false, err
   284  }
   285  
   286  /*
   287  MakeDebugInfo prints bytes in multi-lines.
   288  */
   289  func MakeDebugInfo(data []byte, bytesCount int, bytesPerLine int) string {
   290  	if len(data) == 0 || bytesCount == 0 || bytesPerLine == 0 {
   291  		return ""
   292  	}
   293  	pl := Min(bytesCount, len(data))
   294  	ps := ""
   295  	for i := 0; i < pl; i++ {
   296  		if i > 0 && (i%bytesPerLine == 0) {
   297  			ps += "\n"
   298  		}
   299  		if i%bytesPerLine == 0 {
   300  			ps += fmt.Sprintf("%d", i/bytesPerLine) + " : "
   301  		}
   302  		ps += fmt.Sprintf("%02x ", data[i])
   303  	}
   304  	return ps
   305  }
   306  
   307  func getSystemVariables(configFile string) (*mo_config.FrontendParameters, error) {
   308  	sv := &mo_config.FrontendParameters{}
   309  	var err error
   310  	_, err = toml.DecodeFile(configFile, sv)
   311  	if err != nil {
   312  		return nil, err
   313  	}
   314  	return sv, err
   315  }
   316  
   317  func getParameterUnit(configFile string, eng engine.Engine, txnClient TxnClient) (*mo_config.ParameterUnit, error) {
   318  	sv, err := getSystemVariables(configFile)
   319  	if err != nil {
   320  		return nil, err
   321  	}
   322  	logutil.Info("Using Dump Storage Engine and Cluster Nodes.")
   323  	pu := mo_config.NewParameterUnit(sv, eng, txnClient, engine.Nodes{}, nil)
   324  
   325  	return pu, nil
   326  }
   327  
   328  // WildcardMatch implements wildcard pattern match algorithm.
   329  // pattern and target are ascii characters
   330  // TODO: add \_ and \%
   331  func WildcardMatch(pattern, target string) bool {
   332  	var p = 0
   333  	var t = 0
   334  	var positionOfPercentPlusOne int = -1
   335  	var positionOfTargetEncounterPercent int = -1
   336  	plen := len(pattern)
   337  	tlen := len(target)
   338  	for t < tlen {
   339  		//%
   340  		if p < plen && pattern[p] == '%' {
   341  			p++
   342  			positionOfPercentPlusOne = p
   343  			if p >= plen {
   344  				//pattern end with %
   345  				return true
   346  			}
   347  			//means % matches empty
   348  			positionOfTargetEncounterPercent = t
   349  		} else if p < plen && (pattern[p] == '_' || pattern[p] == target[t]) { //match or _
   350  			p++
   351  			t++
   352  		} else {
   353  			if positionOfPercentPlusOne == -1 {
   354  				//have not matched a %
   355  				return false
   356  			}
   357  			if positionOfTargetEncounterPercent == -1 {
   358  				return false
   359  			}
   360  			//backtrace to last % position + 1
   361  			p = positionOfPercentPlusOne
   362  			//means % matches multiple characters
   363  			positionOfTargetEncounterPercent++
   364  			t = positionOfTargetEncounterPercent
   365  		}
   366  	}
   367  	//skip %
   368  	for p < plen && pattern[p] == '%' {
   369  		p++
   370  	}
   371  	return p >= plen
   372  }
   373  
   374  // only support single value and unary minus
   375  func GetSimpleExprValue(e tree.Expr, ses *Session) (interface{}, error) {
   376  	switch v := e.(type) {
   377  	case *tree.UnresolvedName:
   378  		// set @a = on, type of a is bool.
   379  		return v.Parts[0], nil
   380  	default:
   381  		binder := plan2.NewDefaultBinder(ses.GetRequestContext(), nil, nil, nil, nil)
   382  		planExpr, err := binder.BindExpr(e, 0, false)
   383  		if err != nil {
   384  			return nil, err
   385  		}
   386  		// set @a = 'on', type of a is bool. And mo cast rule does not fit set variable rule so delay to convert type.
   387  		bat := batch.NewWithSize(0)
   388  		bat.Zs = []int64{1}
   389  		vec, err := colexec.EvalExpr(bat, ses.txnCompileCtx.GetProcess(), planExpr)
   390  		if err != nil {
   391  			return nil, err
   392  		}
   393  		return getValueFromVector(vec, ses)
   394  	}
   395  }
   396  
   397  func getValueFromVector(vec *vector.Vector, ses *Session) (interface{}, error) {
   398  	if nulls.Any(vec.Nsp) {
   399  		return nil, nil
   400  	}
   401  	switch vec.Typ.Oid {
   402  	case types.T_bool:
   403  		return vector.GetValueAt[bool](vec, 0), nil
   404  	case types.T_int8:
   405  		return vector.GetValueAt[int8](vec, 0), nil
   406  	case types.T_int16:
   407  		return vector.GetValueAt[int16](vec, 0), nil
   408  	case types.T_int32:
   409  		return vector.GetValueAt[int32](vec, 0), nil
   410  	case types.T_int64:
   411  		return vector.GetValueAt[int64](vec, 0), nil
   412  	case types.T_uint8:
   413  		return vector.GetValueAt[uint8](vec, 0), nil
   414  	case types.T_uint16:
   415  		return vector.GetValueAt[uint16](vec, 0), nil
   416  	case types.T_uint32:
   417  		return vector.GetValueAt[uint32](vec, 0), nil
   418  	case types.T_uint64:
   419  		return vector.GetValueAt[uint64](vec, 0), nil
   420  	case types.T_float32:
   421  		return vector.GetValueAt[float32](vec, 0), nil
   422  	case types.T_float64:
   423  		return vector.GetValueAt[float64](vec, 0), nil
   424  	case types.T_char, types.T_varchar, types.T_text, types.T_blob:
   425  		return vec.GetString(0), nil
   426  	case types.T_decimal64:
   427  		val := vector.GetValueAt[types.Decimal64](vec, 0)
   428  		return val.String(), nil
   429  	case types.T_decimal128:
   430  		val := vector.GetValueAt[types.Decimal128](vec, 0)
   431  		return val.String(), nil
   432  	case types.T_json:
   433  		val := vec.GetBytes(0)
   434  		byteJson := types.DecodeJson(val)
   435  		return byteJson.String(), nil
   436  	case types.T_uuid:
   437  		val := vector.GetValueAt[types.Uuid](vec, 0)
   438  		return val.ToString(), nil
   439  	case types.T_date:
   440  		val := vector.GetValueAt[types.Date](vec, 0)
   441  		return val.String(), nil
   442  	case types.T_time:
   443  		val := vector.GetValueAt[types.Time](vec, 0)
   444  		return val.String(), nil
   445  	case types.T_datetime:
   446  		val := vector.GetValueAt[types.Datetime](vec, 0)
   447  		return val.String(), nil
   448  	case types.T_timestamp:
   449  		val := vector.GetValueAt[types.Timestamp](vec, 0)
   450  		return val.String2(ses.GetTimeZone(), vec.Typ.Precision), nil
   451  	default:
   452  		return nil, moerr.NewInvalidArg(ses.GetRequestContext(), "variable type", vec.Typ.Oid.String())
   453  	}
   454  }
   455  
   456  type statementStatus int
   457  
   458  const (
   459  	success statementStatus = iota
   460  	fail
   461  )
   462  
   463  func (s statementStatus) String() string {
   464  	switch s {
   465  	case success:
   466  		return "success"
   467  	case fail:
   468  		return "fail"
   469  	}
   470  	return "running"
   471  }
   472  
   473  // logStatementStatus prints the status of the statement into the log.
   474  func logStatementStatus(ctx context.Context, ses *Session, stmt tree.Statement, status statementStatus, err error) {
   475  	var stmtStr string
   476  	stm := motrace.StatementFromContext(ctx)
   477  	if stm == nil {
   478  		fmtCtx := tree.NewFmtCtx(dialect.MYSQL)
   479  		stmt.Format(fmtCtx)
   480  		stmtStr = fmtCtx.String()
   481  	} else {
   482  		stmtStr = stm.Statement
   483  	}
   484  	logStatementStringStatus(ctx, ses, stmtStr, status, err)
   485  }
   486  
   487  func logStatementStringStatus(ctx context.Context, ses *Session, stmtStr string, status statementStatus, err error) {
   488  	str := SubStringFromBegin(stmtStr, int(ses.GetParameterUnit().SV.LengthOfQueryPrinted))
   489  	if status == success {
   490  		motrace.EndStatement(ctx, nil)
   491  		logInfo(ses.GetConciseProfile(), "query trace status", logutil.ConnectionIdField(ses.GetConnectionID()), logutil.StatementField(str), logutil.StatusField(status.String()), trace.ContextField(ctx))
   492  	} else {
   493  		motrace.EndStatement(ctx, err)
   494  		logError(ses.GetConciseProfile(), "query trace status", logutil.ConnectionIdField(ses.GetConnectionID()), logutil.StatementField(str), logutil.StatusField(status.String()), logutil.ErrorField(err), trace.ContextField(ctx))
   495  	}
   496  }
   497  
   498  func logInfo(info string, msg string, fields ...zap.Field) {
   499  	fields = append(fields, zap.String("session_info", info))
   500  	logutil.Info(msg, fields...)
   501  }
   502  
   503  //func logDebug(info string, msg string, fields ...zap.Field) {
   504  //	fields = append(fields, zap.String("session_info", info))
   505  //	logutil.Debug(msg, fields...)
   506  //}
   507  
   508  func logError(info string, msg string, fields ...zap.Field) {
   509  	fields = append(fields, zap.String("session_info", info))
   510  	logutil.Error(msg, fields...)
   511  }
   512  
   513  func logInfof(info string, msg string, fields ...interface{}) {
   514  	fields = append(fields, info)
   515  	logutil.Infof(msg+" %s", fields...)
   516  }
   517  
   518  func logDebugf(info string, msg string, fields ...interface{}) {
   519  	fields = append(fields, info)
   520  	logutil.Debugf(msg+" %s", fields...)
   521  }
   522  
   523  func logErrorf(info string, msg string, fields ...interface{}) {
   524  	fields = append(fields, info)
   525  	logutil.Errorf(msg+" %s", fields...)
   526  }
   527  
   528  func fileExists(path string) (bool, error) {
   529  	_, err := os.Stat(path)
   530  	if err == nil {
   531  		return true, nil
   532  	}
   533  	if os.IsNotExist(err) {
   534  		return false, nil
   535  	}
   536  	return false, err
   537  }
   538  
   539  func getAttrFromTableDef(defs []engine.TableDef) ([]string, bool, error) {
   540  	attrs := make([]string, 0, len(defs))
   541  	isView := false
   542  	for _, tblDef := range defs {
   543  		switch def := tblDef.(type) {
   544  		case *engine.AttributeDef:
   545  			if def.Attr.IsHidden || def.Attr.IsRowId {
   546  				continue
   547  			}
   548  			attrs = append(attrs, def.Attr.Name)
   549  		case *engine.ViewDef:
   550  			isView = true
   551  		}
   552  	}
   553  	return attrs, isView, nil
   554  }
   555  
   556  func getDDL(bh BackgroundExec, ctx context.Context, sql string) (string, error) {
   557  	bh.ClearExecResultSet()
   558  	err := bh.Exec(ctx, sql)
   559  	if err != nil {
   560  		return "", err
   561  	}
   562  	ret := string(bh.GetExecResultSet()[0].(*MysqlResultSet).Data[0][1].([]byte))
   563  	if !strings.HasSuffix(ret, ";") {
   564  		ret += ";"
   565  	}
   566  	return ret, nil
   567  }
   568  
   569  func convertValueBat2Str(ctx context.Context, bat *batch.Batch, mp *mpool.MPool, loc *time.Location) (*batch.Batch, error) {
   570  	var err error
   571  	rbat := batch.NewWithSize(bat.VectorCount())
   572  	rbat.InitZsOne(bat.Length())
   573  	for i := 0; i < rbat.VectorCount(); i++ {
   574  		rbat.Vecs[i] = vector.New(types.Type{Oid: types.T_varchar, Width: types.MaxVarcharLen}) //TODO: check size
   575  		rs := make([]string, bat.Length())
   576  		switch bat.Vecs[i].Typ.Oid {
   577  		case types.T_bool:
   578  			xs := vector.MustTCols[bool](bat.Vecs[i])
   579  			rs, err = dumpUtils.ParseBool(xs, bat.GetVector(int32(i)).GetNulls(), rs)
   580  		case types.T_int8:
   581  			xs := vector.MustTCols[int8](bat.Vecs[i])
   582  			rs, err = dumpUtils.ParseSigned(xs, bat.GetVector(int32(i)).GetNulls(), rs)
   583  		case types.T_int16:
   584  			xs := vector.MustTCols[int16](bat.Vecs[i])
   585  			rs, err = dumpUtils.ParseSigned(xs, bat.GetVector(int32(i)).GetNulls(), rs)
   586  		case types.T_int32:
   587  			xs := vector.MustTCols[int32](bat.Vecs[i])
   588  			rs, err = dumpUtils.ParseSigned(xs, bat.GetVector(int32(i)).GetNulls(), rs)
   589  		case types.T_int64:
   590  			xs := vector.MustTCols[int64](bat.Vecs[i])
   591  			rs, err = dumpUtils.ParseSigned(xs, bat.GetVector(int32(i)).GetNulls(), rs)
   592  
   593  		case types.T_uint8:
   594  			xs := vector.MustTCols[uint8](bat.Vecs[i])
   595  			rs, err = dumpUtils.ParseUnsigned(xs, bat.GetVector(int32(i)).GetNulls(), rs)
   596  		case types.T_uint16:
   597  			xs := vector.MustTCols[uint16](bat.Vecs[i])
   598  			rs, err = dumpUtils.ParseUnsigned(xs, bat.GetVector(int32(i)).GetNulls(), rs)
   599  		case types.T_uint32:
   600  			xs := vector.MustTCols[uint32](bat.Vecs[i])
   601  			rs, err = dumpUtils.ParseUnsigned(xs, bat.GetVector(int32(i)).GetNulls(), rs)
   602  
   603  		case types.T_uint64:
   604  			xs := vector.MustTCols[uint64](bat.Vecs[i])
   605  			rs, err = dumpUtils.ParseUnsigned(xs, bat.GetVector(int32(i)).GetNulls(), rs)
   606  		case types.T_float32:
   607  			xs := vector.MustTCols[float32](bat.Vecs[i])
   608  			rs, err = dumpUtils.ParseFloats(xs, bat.GetVector(int32(i)).GetNulls(), rs, 32)
   609  		case types.T_float64:
   610  			xs := vector.MustTCols[float64](bat.Vecs[i])
   611  			rs, err = dumpUtils.ParseFloats(xs, bat.GetVector(int32(i)).GetNulls(), rs, 64)
   612  		case types.T_decimal64:
   613  			xs := vector.MustTCols[types.Decimal64](bat.Vecs[i])
   614  			rs, err = dumpUtils.ParseQuoted(xs, bat.GetVector(int32(i)).GetNulls(), rs, dumpUtils.DefaultParser[types.Decimal64])
   615  		case types.T_decimal128:
   616  			xs := vector.MustTCols[types.Decimal128](bat.Vecs[i])
   617  			rs, err = dumpUtils.ParseQuoted(xs, bat.GetVector(int32(i)).GetNulls(), rs, dumpUtils.DefaultParser[types.Decimal128])
   618  		case types.T_char, types.T_varchar, types.T_blob, types.T_text:
   619  			xs := vector.MustStrCols(bat.Vecs[i])
   620  			rs, err = dumpUtils.ParseQuoted(xs, bat.GetVector(int32(i)).GetNulls(), rs, dumpUtils.DefaultParser[string])
   621  		case types.T_json:
   622  			xs := vector.MustBytesCols(bat.Vecs[i])
   623  			rs, err = dumpUtils.ParseQuoted(xs, bat.GetVector(int32(i)).GetNulls(), rs, dumpUtils.JsonParser)
   624  
   625  		case types.T_timestamp:
   626  			xs := vector.MustTCols[types.Timestamp](bat.Vecs[i])
   627  			rs, err = dumpUtils.ParseTimeStamp(xs, bat.GetVector(int32(i)).GetNulls(), rs, loc, bat.GetVector(int32(i)).Typ.Precision)
   628  		case types.T_datetime:
   629  			xs := vector.MustTCols[types.Datetime](bat.Vecs[i])
   630  			rs, err = dumpUtils.ParseQuoted(xs, bat.GetVector(int32(i)).GetNulls(), rs, dumpUtils.DefaultParser[types.Datetime])
   631  		case types.T_date:
   632  			xs := vector.MustTCols[types.Date](bat.Vecs[i])
   633  			rs, err = dumpUtils.ParseQuoted(xs, bat.GetVector(int32(i)).GetNulls(), rs, dumpUtils.DefaultParser[types.Date])
   634  		case types.T_uuid:
   635  			xs := vector.MustTCols[types.Uuid](bat.Vecs[i])
   636  			rs, err = dumpUtils.ParseUuid(xs, bat.GetVector(int32(i)).GetNulls(), rs)
   637  		default:
   638  			err = moerr.NewNotSupported(ctx, "type %v", bat.Vecs[i].Typ.String())
   639  		}
   640  		if err != nil {
   641  			return nil, err
   642  		}
   643  		for j := 0; j < len(rs); j++ {
   644  			err = rbat.Vecs[i].Append([]byte(rs[j]), false, mp)
   645  			if err != nil {
   646  				return nil, err
   647  			}
   648  		}
   649  	}
   650  	rbat.InitZsOne(bat.Length())
   651  	return rbat, nil
   652  }
   653  
   654  func genDumpFileName(outfile string, idx int64) string {
   655  	path := filepath.Dir(outfile)
   656  	filename := strings.Split(filepath.Base(outfile), ".")
   657  	base, extend := strings.Join(filename[:len(filename)-1], ""), filename[len(filename)-1]
   658  	return filepath.Join(path, fmt.Sprintf("%s_%d.%s", base, idx, extend))
   659  }
   660  
   661  func createDumpFile(ctx context.Context, filename string) (*os.File, error) {
   662  	exists, err := fileExists(filename)
   663  	if err != nil {
   664  		return nil, err
   665  	}
   666  	if exists {
   667  		return nil, moerr.NewFileAlreadyExists(ctx, filename)
   668  	}
   669  
   670  	ret, err := os.Create(filename)
   671  	if err != nil {
   672  		return nil, err
   673  	}
   674  	return ret, nil
   675  }
   676  
   677  func writeDump2File(ctx context.Context, buf *bytes.Buffer, dump *tree.MoDump, f *os.File, curFileIdx, curFileSize int64) (ret *os.File, newFileIdx, newFileSize int64, err error) {
   678  	if dump.MaxFileSize > 0 && int64(buf.Len()) > dump.MaxFileSize {
   679  		err = moerr.NewInternalError(ctx, "dump: data in db is too large,please set a larger max_file_size")
   680  		return
   681  	}
   682  	if dump.MaxFileSize > 0 && curFileSize+int64(buf.Len()) > dump.MaxFileSize {
   683  		f.Close()
   684  		if curFileIdx == 1 {
   685  			os.Rename(dump.OutFile, genDumpFileName(dump.OutFile, curFileIdx))
   686  		}
   687  		newFileIdx = curFileIdx + 1
   688  		newFileSize = int64(buf.Len())
   689  		ret, err = createDumpFile(ctx, genDumpFileName(dump.OutFile, newFileIdx))
   690  		if err != nil {
   691  			return
   692  		}
   693  		_, err = buf.WriteTo(ret)
   694  		if err != nil {
   695  			return
   696  		}
   697  		buf.Reset()
   698  		return
   699  	}
   700  	newFileSize = curFileSize + int64(buf.Len())
   701  	_, err = buf.WriteTo(f)
   702  	if err != nil {
   703  		return
   704  	}
   705  	buf.Reset()
   706  	return f, curFileIdx, newFileSize, nil
   707  }
   708  
   709  func maybeAppendExtension(s string) string {
   710  	path := filepath.Dir(s)
   711  	filename := strings.Split(filepath.Base(s), ".")
   712  	if len(filename) == 1 {
   713  		filename = append(filename, "sql")
   714  	}
   715  	base, extend := strings.Join(filename[:len(filename)-1], ""), filename[len(filename)-1]
   716  	return filepath.Join(path, base+"."+extend)
   717  }
   718  
   719  func removeFile(s string, idx int64) {
   720  	if idx == 1 {
   721  		os.RemoveAll(s)
   722  		return
   723  	}
   724  	path := filepath.Dir(s)
   725  	filename := strings.Split(filepath.Base(s), ".")
   726  	base, extend := strings.Join(filename[:len(filename)-1], ""), filename[len(filename)-1]
   727  	for i := int64(1); i <= idx; i++ {
   728  		os.RemoveAll(filepath.Join(path, fmt.Sprintf("%s_%d.%s", base, i, extend)))
   729  	}
   730  }
   731  
   732  func isInvalidConfigInput(config string) bool {
   733  	// first verify if the input string can parse as a josn type data
   734  	_, err := types.ParseStringToByteJson(config)
   735  	return err != nil
   736  }