github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/memex/builtin_string.go (about)

     1  // Copyright 2020 The ql Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSES/QL-LICENSE file.
     4  
     5  // Copyright 2020 WHTCORPS INC, Inc.
     6  //
     7  // Licensed under the Apache License, Version 2.0 (the "License");
     8  // you may not use this file except in compliance with the License.
     9  // You may obtain a copy of the License at
    10  //
    11  //     http://www.apache.org/licenses/LICENSE-2.0
    12  //
    13  // Unless required by applicable law or agreed to in writing, software
    14  // distributed under the License is distributed on an "AS IS" BASIS,
    15  // See the License for the specific language governing permissions and
    16  // limitations under the License.
    17  
    18  package memex
    19  
    20  import (
    21  	"bytes"
    22  	"encoding/base64"
    23  	"encoding/hex"
    24  	"fmt"
    25  	"math"
    26  	"strconv"
    27  	"strings"
    28  	"unicode/utf8"
    29  
    30  	"github.com/whtcorpsinc/errors"
    31  	"github.com/whtcorpsinc/BerolinaSQL/ast"
    32  	"github.com/whtcorpsinc/BerolinaSQL/charset"
    33  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    34  	"github.com/whtcorpsinc/milevadb/stochastikctx"
    35  	"github.com/whtcorpsinc/milevadb/stochastikctx/variable"
    36  	"github.com/whtcorpsinc/milevadb/types"
    37  	"github.com/whtcorpsinc/milevadb/soliton/chunk"
    38  	"github.com/whtcorpsinc/milevadb/soliton/defCauslate"
    39  	"github.com/whtcorpsinc/milevadb/soliton/replog"
    40  	"github.com/whtcorpsinc/milevadb/soliton/logutil"
    41  	"github.com/whtcorpsinc/fidelpb/go-fidelpb"
    42  	"go.uber.org/zap"
    43  	"golang.org/x/text/transform"
    44  )
    45  
    46  var (
    47  	_ functionClass = &lengthFunctionClass{}
    48  	_ functionClass = &asciiFunctionClass{}
    49  	_ functionClass = &concatFunctionClass{}
    50  	_ functionClass = &concatWSFunctionClass{}
    51  	_ functionClass = &leftFunctionClass{}
    52  	_ functionClass = &repeatFunctionClass{}
    53  	_ functionClass = &lowerFunctionClass{}
    54  	_ functionClass = &reverseFunctionClass{}
    55  	_ functionClass = &spaceFunctionClass{}
    56  	_ functionClass = &upperFunctionClass{}
    57  	_ functionClass = &strcmpFunctionClass{}
    58  	_ functionClass = &replaceFunctionClass{}
    59  	_ functionClass = &convertFunctionClass{}
    60  	_ functionClass = &substringFunctionClass{}
    61  	_ functionClass = &substringIndexFunctionClass{}
    62  	_ functionClass = &locateFunctionClass{}
    63  	_ functionClass = &hexFunctionClass{}
    64  	_ functionClass = &unhexFunctionClass{}
    65  	_ functionClass = &trimFunctionClass{}
    66  	_ functionClass = &lTrimFunctionClass{}
    67  	_ functionClass = &rTrimFunctionClass{}
    68  	_ functionClass = &lpadFunctionClass{}
    69  	_ functionClass = &rpadFunctionClass{}
    70  	_ functionClass = &bitLengthFunctionClass{}
    71  	_ functionClass = &charFunctionClass{}
    72  	_ functionClass = &charLengthFunctionClass{}
    73  	_ functionClass = &findInSetFunctionClass{}
    74  	_ functionClass = &fieldFunctionClass{}
    75  	_ functionClass = &makeSetFunctionClass{}
    76  	_ functionClass = &octFunctionClass{}
    77  	_ functionClass = &ordFunctionClass{}
    78  	_ functionClass = &quoteFunctionClass{}
    79  	_ functionClass = &binFunctionClass{}
    80  	_ functionClass = &eltFunctionClass{}
    81  	_ functionClass = &exportSetFunctionClass{}
    82  	_ functionClass = &formatFunctionClass{}
    83  	_ functionClass = &fromBase64FunctionClass{}
    84  	_ functionClass = &toBase64FunctionClass{}
    85  	_ functionClass = &insertFunctionClass{}
    86  	_ functionClass = &instrFunctionClass{}
    87  	_ functionClass = &loadFileFunctionClass{}
    88  	_ functionClass = &weightStringFunctionClass{}
    89  )
    90  
    91  var (
    92  	_ builtinFunc = &builtinLengthSig{}
    93  	_ builtinFunc = &builtinASCIISig{}
    94  	_ builtinFunc = &builtinConcatSig{}
    95  	_ builtinFunc = &builtinConcatWSSig{}
    96  	_ builtinFunc = &builtinLeftSig{}
    97  	_ builtinFunc = &builtinLeftUTF8Sig{}
    98  	_ builtinFunc = &builtinRightSig{}
    99  	_ builtinFunc = &builtinRightUTF8Sig{}
   100  	_ builtinFunc = &builtinRepeatSig{}
   101  	_ builtinFunc = &builtinLowerSig{}
   102  	_ builtinFunc = &builtinReverseUTF8Sig{}
   103  	_ builtinFunc = &builtinReverseSig{}
   104  	_ builtinFunc = &builtinSpaceSig{}
   105  	_ builtinFunc = &builtinUpperUTF8Sig{}
   106  	_ builtinFunc = &builtinUpperSig{}
   107  	_ builtinFunc = &builtinStrcmpSig{}
   108  	_ builtinFunc = &builtinReplaceSig{}
   109  	_ builtinFunc = &builtinConvertSig{}
   110  	_ builtinFunc = &builtinSubstring2ArgsSig{}
   111  	_ builtinFunc = &builtinSubstring3ArgsSig{}
   112  	_ builtinFunc = &builtinSubstring2ArgsUTF8Sig{}
   113  	_ builtinFunc = &builtinSubstring3ArgsUTF8Sig{}
   114  	_ builtinFunc = &builtinSubstringIndexSig{}
   115  	_ builtinFunc = &builtinLocate2ArgsUTF8Sig{}
   116  	_ builtinFunc = &builtinLocate3ArgsUTF8Sig{}
   117  	_ builtinFunc = &builtinLocate2ArgsSig{}
   118  	_ builtinFunc = &builtinLocate3ArgsSig{}
   119  	_ builtinFunc = &builtinHexStrArgSig{}
   120  	_ builtinFunc = &builtinHexIntArgSig{}
   121  	_ builtinFunc = &builtinUnHexSig{}
   122  	_ builtinFunc = &builtinTrim1ArgSig{}
   123  	_ builtinFunc = &builtinTrim2ArgsSig{}
   124  	_ builtinFunc = &builtinTrim3ArgsSig{}
   125  	_ builtinFunc = &builtinLTrimSig{}
   126  	_ builtinFunc = &builtinRTrimSig{}
   127  	_ builtinFunc = &builtinLpadUTF8Sig{}
   128  	_ builtinFunc = &builtinLpadSig{}
   129  	_ builtinFunc = &builtinRpadUTF8Sig{}
   130  	_ builtinFunc = &builtinRpadSig{}
   131  	_ builtinFunc = &builtinBitLengthSig{}
   132  	_ builtinFunc = &builtinCharSig{}
   133  	_ builtinFunc = &builtinCharLengthUTF8Sig{}
   134  	_ builtinFunc = &builtinFindInSetSig{}
   135  	_ builtinFunc = &builtinMakeSetSig{}
   136  	_ builtinFunc = &builtinOctIntSig{}
   137  	_ builtinFunc = &builtinOctStringSig{}
   138  	_ builtinFunc = &builtinOrdSig{}
   139  	_ builtinFunc = &builtinQuoteSig{}
   140  	_ builtinFunc = &builtinBinSig{}
   141  	_ builtinFunc = &builtinEltSig{}
   142  	_ builtinFunc = &builtinExportSet3ArgSig{}
   143  	_ builtinFunc = &builtinExportSet4ArgSig{}
   144  	_ builtinFunc = &builtinExportSet5ArgSig{}
   145  	_ builtinFunc = &builtinFormatWithLocaleSig{}
   146  	_ builtinFunc = &builtinFormatSig{}
   147  	_ builtinFunc = &builtinFromBase64Sig{}
   148  	_ builtinFunc = &builtinToBase64Sig{}
   149  	_ builtinFunc = &builtinInsertSig{}
   150  	_ builtinFunc = &builtinInsertUTF8Sig{}
   151  	_ builtinFunc = &builtinInstrUTF8Sig{}
   152  	_ builtinFunc = &builtinInstrSig{}
   153  	_ builtinFunc = &builtinFieldRealSig{}
   154  	_ builtinFunc = &builtinFieldIntSig{}
   155  	_ builtinFunc = &builtinFieldStringSig{}
   156  	_ builtinFunc = &builtinWeightStringSig{}
   157  )
   158  
   159  func reverseBytes(origin []byte) []byte {
   160  	for i, length := 0, len(origin); i < length/2; i++ {
   161  		origin[i], origin[length-i-1] = origin[length-i-1], origin[i]
   162  	}
   163  	return origin
   164  }
   165  
   166  func reverseRunes(origin []rune) []rune {
   167  	for i, length := 0, len(origin); i < length/2; i++ {
   168  		origin[i], origin[length-i-1] = origin[length-i-1], origin[i]
   169  	}
   170  	return origin
   171  }
   172  
   173  // SetBinFlagOrBinStr sets resTp to binary string if argTp is a binary string,
   174  // if not, sets the binary flag of resTp to true if argTp has binary flag.
   175  func SetBinFlagOrBinStr(argTp *types.FieldType, resTp *types.FieldType) {
   176  	if types.IsBinaryStr(argTp) {
   177  		types.SetBinChsClnFlag(resTp)
   178  	} else if allegrosql.HasBinaryFlag(argTp.Flag) || !types.IsNonBinaryStr(argTp) {
   179  		resTp.Flag |= allegrosql.BinaryFlag
   180  	}
   181  }
   182  
   183  type lengthFunctionClass struct {
   184  	baseFunctionClass
   185  }
   186  
   187  func (c *lengthFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
   188  	if err := c.verifyArgs(args); err != nil {
   189  		return nil, err
   190  	}
   191  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETString)
   192  	if err != nil {
   193  		return nil, err
   194  	}
   195  	bf.tp.Flen = 10
   196  	sig := &builtinLengthSig{bf}
   197  	sig.setPbCode(fidelpb.ScalarFuncSig_Length)
   198  	return sig, nil
   199  }
   200  
   201  type builtinLengthSig struct {
   202  	baseBuiltinFunc
   203  }
   204  
   205  func (b *builtinLengthSig) Clone() builtinFunc {
   206  	newSig := &builtinLengthSig{}
   207  	newSig.cloneFrom(&b.baseBuiltinFunc)
   208  	return newSig
   209  }
   210  
   211  // evalInt evaluates a builtinLengthSig.
   212  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html
   213  func (b *builtinLengthSig) evalInt(event chunk.Event) (int64, bool, error) {
   214  	val, isNull, err := b.args[0].EvalString(b.ctx, event)
   215  	if isNull || err != nil {
   216  		return 0, isNull, err
   217  	}
   218  	return int64(len([]byte(val))), false, nil
   219  }
   220  
   221  type asciiFunctionClass struct {
   222  	baseFunctionClass
   223  }
   224  
   225  func (c *asciiFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
   226  	if err := c.verifyArgs(args); err != nil {
   227  		return nil, err
   228  	}
   229  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETString)
   230  	if err != nil {
   231  		return nil, err
   232  	}
   233  	bf.tp.Flen = 3
   234  	sig := &builtinASCIISig{bf}
   235  	sig.setPbCode(fidelpb.ScalarFuncSig_ASCII)
   236  	return sig, nil
   237  }
   238  
   239  type builtinASCIISig struct {
   240  	baseBuiltinFunc
   241  }
   242  
   243  func (b *builtinASCIISig) Clone() builtinFunc {
   244  	newSig := &builtinASCIISig{}
   245  	newSig.cloneFrom(&b.baseBuiltinFunc)
   246  	return newSig
   247  }
   248  
   249  // evalInt evals a builtinASCIISig.
   250  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_ascii
   251  func (b *builtinASCIISig) evalInt(event chunk.Event) (int64, bool, error) {
   252  	val, isNull, err := b.args[0].EvalString(b.ctx, event)
   253  	if isNull || err != nil {
   254  		return 0, isNull, err
   255  	}
   256  	if len(val) == 0 {
   257  		return 0, false, nil
   258  	}
   259  	return int64(val[0]), false, nil
   260  }
   261  
   262  type concatFunctionClass struct {
   263  	baseFunctionClass
   264  }
   265  
   266  func (c *concatFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
   267  	if err := c.verifyArgs(args); err != nil {
   268  		return nil, err
   269  	}
   270  	argTps := make([]types.EvalType, 0, len(args))
   271  	for i := 0; i < len(args); i++ {
   272  		argTps = append(argTps, types.ETString)
   273  	}
   274  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, argTps...)
   275  	if err != nil {
   276  		return nil, err
   277  	}
   278  	bf.tp.Flen = 0
   279  	for i := range args {
   280  		argType := args[i].GetType()
   281  		SetBinFlagOrBinStr(argType, bf.tp)
   282  
   283  		if argType.Flen < 0 {
   284  			bf.tp.Flen = allegrosql.MaxBlobWidth
   285  			logutil.BgLogger().Warn("unexpected `Flen` value(-1) in CONCAT's args", zap.Int("arg's index", i))
   286  		}
   287  		bf.tp.Flen += argType.Flen
   288  	}
   289  	if bf.tp.Flen >= allegrosql.MaxBlobWidth {
   290  		bf.tp.Flen = allegrosql.MaxBlobWidth
   291  	}
   292  
   293  	valStr, _ := ctx.GetStochastikVars().GetSystemVar(variable.MaxAllowedPacket)
   294  	maxAllowedPacket, err := strconv.ParseUint(valStr, 10, 64)
   295  	if err != nil {
   296  		return nil, errors.Trace(err)
   297  	}
   298  
   299  	sig := &builtinConcatSig{bf, maxAllowedPacket}
   300  	sig.setPbCode(fidelpb.ScalarFuncSig_Concat)
   301  	return sig, nil
   302  }
   303  
   304  type builtinConcatSig struct {
   305  	baseBuiltinFunc
   306  	maxAllowedPacket uint64
   307  }
   308  
   309  func (b *builtinConcatSig) Clone() builtinFunc {
   310  	newSig := &builtinConcatSig{}
   311  	newSig.cloneFrom(&b.baseBuiltinFunc)
   312  	newSig.maxAllowedPacket = b.maxAllowedPacket
   313  	return newSig
   314  }
   315  
   316  // evalString evals a builtinConcatSig
   317  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_concat
   318  func (b *builtinConcatSig) evalString(event chunk.Event) (d string, isNull bool, err error) {
   319  	var s []byte
   320  	for _, a := range b.getArgs() {
   321  		d, isNull, err = a.EvalString(b.ctx, event)
   322  		if isNull || err != nil {
   323  			return d, isNull, err
   324  		}
   325  		if uint64(len(s)+len(d)) > b.maxAllowedPacket {
   326  			b.ctx.GetStochastikVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("concat", b.maxAllowedPacket))
   327  			return "", true, nil
   328  		}
   329  		s = append(s, []byte(d)...)
   330  	}
   331  	return string(s), false, nil
   332  }
   333  
   334  type concatWSFunctionClass struct {
   335  	baseFunctionClass
   336  }
   337  
   338  func (c *concatWSFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
   339  	if err := c.verifyArgs(args); err != nil {
   340  		return nil, err
   341  	}
   342  	argTps := make([]types.EvalType, 0, len(args))
   343  	for i := 0; i < len(args); i++ {
   344  		argTps = append(argTps, types.ETString)
   345  	}
   346  
   347  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, argTps...)
   348  	if err != nil {
   349  		return nil, err
   350  	}
   351  	bf.tp.Flen = 0
   352  
   353  	for i := range args {
   354  		argType := args[i].GetType()
   355  		SetBinFlagOrBinStr(argType, bf.tp)
   356  
   357  		// skip separator param
   358  		if i != 0 {
   359  			if argType.Flen < 0 {
   360  				bf.tp.Flen = allegrosql.MaxBlobWidth
   361  				logutil.BgLogger().Warn("unexpected `Flen` value(-1) in CONCAT_WS's args", zap.Int("arg's index", i))
   362  			}
   363  			bf.tp.Flen += argType.Flen
   364  		}
   365  	}
   366  
   367  	// add separator
   368  	argsLen := len(args) - 1
   369  	bf.tp.Flen += argsLen - 1
   370  
   371  	if bf.tp.Flen >= allegrosql.MaxBlobWidth {
   372  		bf.tp.Flen = allegrosql.MaxBlobWidth
   373  	}
   374  
   375  	valStr, _ := ctx.GetStochastikVars().GetSystemVar(variable.MaxAllowedPacket)
   376  	maxAllowedPacket, err := strconv.ParseUint(valStr, 10, 64)
   377  	if err != nil {
   378  		return nil, errors.Trace(err)
   379  	}
   380  
   381  	sig := &builtinConcatWSSig{bf, maxAllowedPacket}
   382  	sig.setPbCode(fidelpb.ScalarFuncSig_ConcatWS)
   383  	return sig, nil
   384  }
   385  
   386  type builtinConcatWSSig struct {
   387  	baseBuiltinFunc
   388  	maxAllowedPacket uint64
   389  }
   390  
   391  func (b *builtinConcatWSSig) Clone() builtinFunc {
   392  	newSig := &builtinConcatWSSig{}
   393  	newSig.cloneFrom(&b.baseBuiltinFunc)
   394  	newSig.maxAllowedPacket = b.maxAllowedPacket
   395  	return newSig
   396  }
   397  
   398  // evalString evals a CONCAT_WS(separator,str1,str2,...).
   399  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_concat-ws
   400  func (b *builtinConcatWSSig) evalString(event chunk.Event) (string, bool, error) {
   401  	args := b.getArgs()
   402  	strs := make([]string, 0, len(args))
   403  	var sep string
   404  	var targetLength int
   405  
   406  	N := len(args)
   407  	if N > 0 {
   408  		val, isNull, err := args[0].EvalString(b.ctx, event)
   409  		if err != nil || isNull {
   410  			// If the separator is NULL, the result is NULL.
   411  			return val, isNull, err
   412  		}
   413  		sep = val
   414  	}
   415  	for i := 1; i < N; i++ {
   416  		val, isNull, err := args[i].EvalString(b.ctx, event)
   417  		if err != nil {
   418  			return val, isNull, err
   419  		}
   420  		if isNull {
   421  			// CONCAT_WS() does not skip empty strings. However,
   422  			// it does skip any NULL values after the separator argument.
   423  			continue
   424  		}
   425  
   426  		targetLength += len(val)
   427  		if i > 1 {
   428  			targetLength += len(sep)
   429  		}
   430  		if uint64(targetLength) > b.maxAllowedPacket {
   431  			b.ctx.GetStochastikVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("concat_ws", b.maxAllowedPacket))
   432  			return "", true, nil
   433  		}
   434  		strs = append(strs, val)
   435  	}
   436  
   437  	str := strings.Join(strs, sep)
   438  	// todo check whether the length of result is larger than Flen
   439  	//if b.tp.Flen != types.UnspecifiedLength && len(str) > b.tp.Flen {
   440  	//	return "", true, nil
   441  	//}
   442  	return str, false, nil
   443  }
   444  
   445  type leftFunctionClass struct {
   446  	baseFunctionClass
   447  }
   448  
   449  func (c *leftFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
   450  	if err := c.verifyArgs(args); err != nil {
   451  		return nil, err
   452  	}
   453  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString, types.ETInt)
   454  	if err != nil {
   455  		return nil, err
   456  	}
   457  	argType := args[0].GetType()
   458  	bf.tp.Flen = argType.Flen
   459  	SetBinFlagOrBinStr(argType, bf.tp)
   460  	if types.IsBinaryStr(argType) {
   461  		sig := &builtinLeftSig{bf}
   462  		sig.setPbCode(fidelpb.ScalarFuncSig_Left)
   463  		return sig, nil
   464  	}
   465  	sig := &builtinLeftUTF8Sig{bf}
   466  	sig.setPbCode(fidelpb.ScalarFuncSig_LeftUTF8)
   467  	return sig, nil
   468  }
   469  
   470  type builtinLeftSig struct {
   471  	baseBuiltinFunc
   472  }
   473  
   474  func (b *builtinLeftSig) Clone() builtinFunc {
   475  	newSig := &builtinLeftSig{}
   476  	newSig.cloneFrom(&b.baseBuiltinFunc)
   477  	return newSig
   478  }
   479  
   480  // evalString evals LEFT(str,len).
   481  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_left
   482  func (b *builtinLeftSig) evalString(event chunk.Event) (string, bool, error) {
   483  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
   484  	if isNull || err != nil {
   485  		return "", true, err
   486  	}
   487  	left, isNull, err := b.args[1].EvalInt(b.ctx, event)
   488  	if isNull || err != nil {
   489  		return "", true, err
   490  	}
   491  	leftLength := int(left)
   492  	if strLength := len(str); leftLength > strLength {
   493  		leftLength = strLength
   494  	} else if leftLength < 0 {
   495  		leftLength = 0
   496  	}
   497  	return str[:leftLength], false, nil
   498  }
   499  
   500  type builtinLeftUTF8Sig struct {
   501  	baseBuiltinFunc
   502  }
   503  
   504  func (b *builtinLeftUTF8Sig) Clone() builtinFunc {
   505  	newSig := &builtinLeftUTF8Sig{}
   506  	newSig.cloneFrom(&b.baseBuiltinFunc)
   507  	return newSig
   508  }
   509  
   510  // evalString evals LEFT(str,len).
   511  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_left
   512  func (b *builtinLeftUTF8Sig) evalString(event chunk.Event) (string, bool, error) {
   513  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
   514  	if isNull || err != nil {
   515  		return "", true, err
   516  	}
   517  	left, isNull, err := b.args[1].EvalInt(b.ctx, event)
   518  	if isNull || err != nil {
   519  		return "", true, err
   520  	}
   521  	runes, leftLength := []rune(str), int(left)
   522  	if runeLength := len(runes); leftLength > runeLength {
   523  		leftLength = runeLength
   524  	} else if leftLength < 0 {
   525  		leftLength = 0
   526  	}
   527  	return string(runes[:leftLength]), false, nil
   528  }
   529  
   530  type rightFunctionClass struct {
   531  	baseFunctionClass
   532  }
   533  
   534  func (c *rightFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
   535  	if err := c.verifyArgs(args); err != nil {
   536  		return nil, err
   537  	}
   538  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString, types.ETInt)
   539  	if err != nil {
   540  		return nil, err
   541  	}
   542  	argType := args[0].GetType()
   543  	bf.tp.Flen = argType.Flen
   544  	SetBinFlagOrBinStr(argType, bf.tp)
   545  	if types.IsBinaryStr(argType) {
   546  		sig := &builtinRightSig{bf}
   547  		sig.setPbCode(fidelpb.ScalarFuncSig_Right)
   548  		return sig, nil
   549  	}
   550  	sig := &builtinRightUTF8Sig{bf}
   551  	sig.setPbCode(fidelpb.ScalarFuncSig_RightUTF8)
   552  	return sig, nil
   553  }
   554  
   555  type builtinRightSig struct {
   556  	baseBuiltinFunc
   557  }
   558  
   559  func (b *builtinRightSig) Clone() builtinFunc {
   560  	newSig := &builtinRightSig{}
   561  	newSig.cloneFrom(&b.baseBuiltinFunc)
   562  	return newSig
   563  }
   564  
   565  // evalString evals RIGHT(str,len).
   566  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_right
   567  func (b *builtinRightSig) evalString(event chunk.Event) (string, bool, error) {
   568  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
   569  	if isNull || err != nil {
   570  		return "", true, err
   571  	}
   572  	right, isNull, err := b.args[1].EvalInt(b.ctx, event)
   573  	if isNull || err != nil {
   574  		return "", true, err
   575  	}
   576  	strLength, rightLength := len(str), int(right)
   577  	if rightLength > strLength {
   578  		rightLength = strLength
   579  	} else if rightLength < 0 {
   580  		rightLength = 0
   581  	}
   582  	return str[strLength-rightLength:], false, nil
   583  }
   584  
   585  type builtinRightUTF8Sig struct {
   586  	baseBuiltinFunc
   587  }
   588  
   589  func (b *builtinRightUTF8Sig) Clone() builtinFunc {
   590  	newSig := &builtinRightUTF8Sig{}
   591  	newSig.cloneFrom(&b.baseBuiltinFunc)
   592  	return newSig
   593  }
   594  
   595  // evalString evals RIGHT(str,len).
   596  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_right
   597  func (b *builtinRightUTF8Sig) evalString(event chunk.Event) (string, bool, error) {
   598  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
   599  	if isNull || err != nil {
   600  		return "", true, err
   601  	}
   602  	right, isNull, err := b.args[1].EvalInt(b.ctx, event)
   603  	if isNull || err != nil {
   604  		return "", true, err
   605  	}
   606  	runes := []rune(str)
   607  	strLength, rightLength := len(runes), int(right)
   608  	if rightLength > strLength {
   609  		rightLength = strLength
   610  	} else if rightLength < 0 {
   611  		rightLength = 0
   612  	}
   613  	return string(runes[strLength-rightLength:]), false, nil
   614  }
   615  
   616  type repeatFunctionClass struct {
   617  	baseFunctionClass
   618  }
   619  
   620  func (c *repeatFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
   621  	if err := c.verifyArgs(args); err != nil {
   622  		return nil, err
   623  	}
   624  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString, types.ETInt)
   625  	if err != nil {
   626  		return nil, err
   627  	}
   628  	bf.tp.Flen = allegrosql.MaxBlobWidth
   629  	SetBinFlagOrBinStr(args[0].GetType(), bf.tp)
   630  	valStr, _ := ctx.GetStochastikVars().GetSystemVar(variable.MaxAllowedPacket)
   631  	maxAllowedPacket, err := strconv.ParseUint(valStr, 10, 64)
   632  	if err != nil {
   633  		return nil, errors.Trace(err)
   634  	}
   635  	sig := &builtinRepeatSig{bf, maxAllowedPacket}
   636  	return sig, nil
   637  }
   638  
   639  type builtinRepeatSig struct {
   640  	baseBuiltinFunc
   641  	maxAllowedPacket uint64
   642  }
   643  
   644  func (b *builtinRepeatSig) Clone() builtinFunc {
   645  	newSig := &builtinRepeatSig{}
   646  	newSig.cloneFrom(&b.baseBuiltinFunc)
   647  	newSig.maxAllowedPacket = b.maxAllowedPacket
   648  	return newSig
   649  }
   650  
   651  // evalString evals a builtinRepeatSig.
   652  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_repeat
   653  func (b *builtinRepeatSig) evalString(event chunk.Event) (d string, isNull bool, err error) {
   654  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
   655  	if isNull || err != nil {
   656  		return "", isNull, err
   657  	}
   658  	byteLength := len(str)
   659  
   660  	num, isNull, err := b.args[1].EvalInt(b.ctx, event)
   661  	if isNull || err != nil {
   662  		return "", isNull, err
   663  	}
   664  	if num < 1 {
   665  		return "", false, nil
   666  	}
   667  	if num > math.MaxInt32 {
   668  		num = math.MaxInt32
   669  	}
   670  
   671  	if uint64(byteLength)*uint64(num) > b.maxAllowedPacket {
   672  		b.ctx.GetStochastikVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("repeat", b.maxAllowedPacket))
   673  		return "", true, nil
   674  	}
   675  
   676  	if int64(byteLength) > int64(b.tp.Flen)/num {
   677  		return "", true, nil
   678  	}
   679  	return strings.Repeat(str, int(num)), false, nil
   680  }
   681  
   682  type lowerFunctionClass struct {
   683  	baseFunctionClass
   684  }
   685  
   686  func (c *lowerFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
   687  	if err := c.verifyArgs(args); err != nil {
   688  		return nil, err
   689  	}
   690  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString)
   691  	if err != nil {
   692  		return nil, err
   693  	}
   694  	argTp := args[0].GetType()
   695  	bf.tp.Flen = argTp.Flen
   696  	SetBinFlagOrBinStr(argTp, bf.tp)
   697  	sig := &builtinLowerSig{bf}
   698  	sig.setPbCode(fidelpb.ScalarFuncSig_Lower)
   699  	return sig, nil
   700  }
   701  
   702  type builtinLowerSig struct {
   703  	baseBuiltinFunc
   704  }
   705  
   706  func (b *builtinLowerSig) Clone() builtinFunc {
   707  	newSig := &builtinLowerSig{}
   708  	newSig.cloneFrom(&b.baseBuiltinFunc)
   709  	return newSig
   710  }
   711  
   712  // evalString evals a builtinLowerSig.
   713  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_lower
   714  func (b *builtinLowerSig) evalString(event chunk.Event) (d string, isNull bool, err error) {
   715  	d, isNull, err = b.args[0].EvalString(b.ctx, event)
   716  	if isNull || err != nil {
   717  		return d, isNull, err
   718  	}
   719  
   720  	if types.IsBinaryStr(b.args[0].GetType()) {
   721  		return d, false, nil
   722  	}
   723  
   724  	return strings.ToLower(d), false, nil
   725  }
   726  
   727  type reverseFunctionClass struct {
   728  	baseFunctionClass
   729  }
   730  
   731  func (c *reverseFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
   732  	if err := c.verifyArgs(args); err != nil {
   733  		return nil, err
   734  	}
   735  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString)
   736  	if err != nil {
   737  		return nil, err
   738  	}
   739  	retTp := *args[0].GetType()
   740  	retTp.Tp = allegrosql.TypeVarString
   741  	retTp.Decimal = types.UnspecifiedLength
   742  	bf.tp = &retTp
   743  	var sig builtinFunc
   744  	if types.IsBinaryStr(bf.tp) {
   745  		sig = &builtinReverseSig{bf}
   746  		sig.setPbCode(fidelpb.ScalarFuncSig_Reverse)
   747  	} else {
   748  		sig = &builtinReverseUTF8Sig{bf}
   749  		sig.setPbCode(fidelpb.ScalarFuncSig_ReverseUTF8)
   750  	}
   751  	return sig, nil
   752  }
   753  
   754  type builtinReverseSig struct {
   755  	baseBuiltinFunc
   756  }
   757  
   758  func (b *builtinReverseSig) Clone() builtinFunc {
   759  	newSig := &builtinReverseSig{}
   760  	newSig.cloneFrom(&b.baseBuiltinFunc)
   761  	return newSig
   762  }
   763  
   764  // evalString evals a REVERSE(str).
   765  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_reverse
   766  func (b *builtinReverseSig) evalString(event chunk.Event) (string, bool, error) {
   767  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
   768  	if isNull || err != nil {
   769  		return "", true, err
   770  	}
   771  	reversed := reverseBytes([]byte(str))
   772  	return string(reversed), false, nil
   773  }
   774  
   775  type builtinReverseUTF8Sig struct {
   776  	baseBuiltinFunc
   777  }
   778  
   779  func (b *builtinReverseUTF8Sig) Clone() builtinFunc {
   780  	newSig := &builtinReverseUTF8Sig{}
   781  	newSig.cloneFrom(&b.baseBuiltinFunc)
   782  	return newSig
   783  }
   784  
   785  // evalString evals a REVERSE(str).
   786  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_reverse
   787  func (b *builtinReverseUTF8Sig) evalString(event chunk.Event) (string, bool, error) {
   788  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
   789  	if isNull || err != nil {
   790  		return "", true, err
   791  	}
   792  	reversed := reverseRunes([]rune(str))
   793  	return string(reversed), false, nil
   794  }
   795  
   796  type spaceFunctionClass struct {
   797  	baseFunctionClass
   798  }
   799  
   800  func (c *spaceFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
   801  	if err := c.verifyArgs(args); err != nil {
   802  		return nil, err
   803  	}
   804  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETInt)
   805  	if err != nil {
   806  		return nil, err
   807  	}
   808  	bf.tp.Charset, bf.tp.DefCauslate = ctx.GetStochastikVars().GetCharsetInfo()
   809  	bf.tp.Flen = allegrosql.MaxBlobWidth
   810  	valStr, _ := ctx.GetStochastikVars().GetSystemVar(variable.MaxAllowedPacket)
   811  	maxAllowedPacket, err := strconv.ParseUint(valStr, 10, 64)
   812  	if err != nil {
   813  		return nil, errors.Trace(err)
   814  	}
   815  	sig := &builtinSpaceSig{bf, maxAllowedPacket}
   816  	sig.setPbCode(fidelpb.ScalarFuncSig_Space)
   817  	return sig, nil
   818  }
   819  
   820  type builtinSpaceSig struct {
   821  	baseBuiltinFunc
   822  	maxAllowedPacket uint64
   823  }
   824  
   825  func (b *builtinSpaceSig) Clone() builtinFunc {
   826  	newSig := &builtinSpaceSig{}
   827  	newSig.cloneFrom(&b.baseBuiltinFunc)
   828  	newSig.maxAllowedPacket = b.maxAllowedPacket
   829  	return newSig
   830  }
   831  
   832  // evalString evals a builtinSpaceSig.
   833  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_space
   834  func (b *builtinSpaceSig) evalString(event chunk.Event) (d string, isNull bool, err error) {
   835  	var x int64
   836  
   837  	x, isNull, err = b.args[0].EvalInt(b.ctx, event)
   838  	if isNull || err != nil {
   839  		return d, isNull, err
   840  	}
   841  	if x < 0 {
   842  		x = 0
   843  	}
   844  	if uint64(x) > b.maxAllowedPacket {
   845  		b.ctx.GetStochastikVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("space", b.maxAllowedPacket))
   846  		return d, true, nil
   847  	}
   848  	if x > allegrosql.MaxBlobWidth {
   849  		return d, true, nil
   850  	}
   851  	return strings.Repeat(" ", int(x)), false, nil
   852  }
   853  
   854  type upperFunctionClass struct {
   855  	baseFunctionClass
   856  }
   857  
   858  func (c *upperFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
   859  	if err := c.verifyArgs(args); err != nil {
   860  		return nil, err
   861  	}
   862  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString)
   863  	if err != nil {
   864  		return nil, err
   865  	}
   866  	argTp := args[0].GetType()
   867  	bf.tp.Flen = argTp.Flen
   868  	SetBinFlagOrBinStr(argTp, bf.tp)
   869  	var sig builtinFunc
   870  	if types.IsBinaryStr(argTp) {
   871  		sig = &builtinUpperSig{bf}
   872  		sig.setPbCode(fidelpb.ScalarFuncSig_Upper)
   873  	} else {
   874  		sig = &builtinUpperUTF8Sig{bf}
   875  		sig.setPbCode(fidelpb.ScalarFuncSig_UpperUTF8)
   876  	}
   877  	return sig, nil
   878  }
   879  
   880  type builtinUpperUTF8Sig struct {
   881  	baseBuiltinFunc
   882  }
   883  
   884  func (b *builtinUpperUTF8Sig) Clone() builtinFunc {
   885  	newSig := &builtinUpperUTF8Sig{}
   886  	newSig.cloneFrom(&b.baseBuiltinFunc)
   887  	return newSig
   888  }
   889  
   890  // evalString evals a builtinUpperUTF8Sig.
   891  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_upper
   892  func (b *builtinUpperUTF8Sig) evalString(event chunk.Event) (d string, isNull bool, err error) {
   893  	d, isNull, err = b.args[0].EvalString(b.ctx, event)
   894  	if isNull || err != nil {
   895  		return d, isNull, err
   896  	}
   897  
   898  	return strings.ToUpper(d), false, nil
   899  }
   900  
   901  type builtinUpperSig struct {
   902  	baseBuiltinFunc
   903  }
   904  
   905  func (b *builtinUpperSig) Clone() builtinFunc {
   906  	newSig := &builtinUpperSig{}
   907  	newSig.cloneFrom(&b.baseBuiltinFunc)
   908  	return newSig
   909  }
   910  
   911  // evalString evals a builtinUpperSig.
   912  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_upper
   913  func (b *builtinUpperSig) evalString(event chunk.Event) (d string, isNull bool, err error) {
   914  	d, isNull, err = b.args[0].EvalString(b.ctx, event)
   915  	if isNull || err != nil {
   916  		return d, isNull, err
   917  	}
   918  
   919  	return d, false, nil
   920  }
   921  
   922  type strcmpFunctionClass struct {
   923  	baseFunctionClass
   924  }
   925  
   926  func (c *strcmpFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
   927  	if err := c.verifyArgs(args); err != nil {
   928  		return nil, err
   929  	}
   930  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETString, types.ETString)
   931  	if err != nil {
   932  		return nil, err
   933  	}
   934  	bf.tp.Flen = 2
   935  	types.SetBinChsClnFlag(bf.tp)
   936  	sig := &builtinStrcmpSig{bf}
   937  	sig.setPbCode(fidelpb.ScalarFuncSig_Strcmp)
   938  	return sig, nil
   939  }
   940  
   941  type builtinStrcmpSig struct {
   942  	baseBuiltinFunc
   943  }
   944  
   945  func (b *builtinStrcmpSig) Clone() builtinFunc {
   946  	newSig := &builtinStrcmpSig{}
   947  	newSig.cloneFrom(&b.baseBuiltinFunc)
   948  	return newSig
   949  }
   950  
   951  // evalInt evals a builtinStrcmpSig.
   952  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-comparison-functions.html
   953  func (b *builtinStrcmpSig) evalInt(event chunk.Event) (int64, bool, error) {
   954  	var (
   955  		left, right string
   956  		isNull      bool
   957  		err         error
   958  	)
   959  
   960  	left, isNull, err = b.args[0].EvalString(b.ctx, event)
   961  	if isNull || err != nil {
   962  		return 0, isNull, err
   963  	}
   964  	right, isNull, err = b.args[1].EvalString(b.ctx, event)
   965  	if isNull || err != nil {
   966  		return 0, isNull, err
   967  	}
   968  	res := types.CompareString(left, right, b.defCauslation)
   969  	return int64(res), false, nil
   970  }
   971  
   972  type replaceFunctionClass struct {
   973  	baseFunctionClass
   974  }
   975  
   976  func (c *replaceFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
   977  	if err := c.verifyArgs(args); err != nil {
   978  		return nil, err
   979  	}
   980  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString, types.ETString, types.ETString)
   981  	if err != nil {
   982  		return nil, err
   983  	}
   984  	bf.tp.Flen = c.fixLength(args)
   985  	for _, a := range args {
   986  		SetBinFlagOrBinStr(a.GetType(), bf.tp)
   987  	}
   988  	sig := &builtinReplaceSig{bf}
   989  	sig.setPbCode(fidelpb.ScalarFuncSig_Replace)
   990  	return sig, nil
   991  }
   992  
   993  // fixLength calculate the Flen of the return type.
   994  func (c *replaceFunctionClass) fixLength(args []Expression) int {
   995  	charLen := args[0].GetType().Flen
   996  	oldStrLen := args[1].GetType().Flen
   997  	diff := args[2].GetType().Flen - oldStrLen
   998  	if diff > 0 && oldStrLen > 0 {
   999  		charLen += (charLen / oldStrLen) * diff
  1000  	}
  1001  	return charLen
  1002  }
  1003  
  1004  type builtinReplaceSig struct {
  1005  	baseBuiltinFunc
  1006  }
  1007  
  1008  func (b *builtinReplaceSig) Clone() builtinFunc {
  1009  	newSig := &builtinReplaceSig{}
  1010  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1011  	return newSig
  1012  }
  1013  
  1014  // evalString evals a builtinReplaceSig.
  1015  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_replace
  1016  func (b *builtinReplaceSig) evalString(event chunk.Event) (d string, isNull bool, err error) {
  1017  	var str, oldStr, newStr string
  1018  
  1019  	str, isNull, err = b.args[0].EvalString(b.ctx, event)
  1020  	if isNull || err != nil {
  1021  		return d, isNull, err
  1022  	}
  1023  	oldStr, isNull, err = b.args[1].EvalString(b.ctx, event)
  1024  	if isNull || err != nil {
  1025  		return d, isNull, err
  1026  	}
  1027  	newStr, isNull, err = b.args[2].EvalString(b.ctx, event)
  1028  	if isNull || err != nil {
  1029  		return d, isNull, err
  1030  	}
  1031  	if oldStr == "" {
  1032  		return str, false, nil
  1033  	}
  1034  	return strings.Replace(str, oldStr, newStr, -1), false, nil
  1035  }
  1036  
  1037  type convertFunctionClass struct {
  1038  	baseFunctionClass
  1039  }
  1040  
  1041  func (c *convertFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  1042  	if err := c.verifyArgs(args); err != nil {
  1043  		return nil, err
  1044  	}
  1045  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString, types.ETString)
  1046  	if err != nil {
  1047  		return nil, err
  1048  	}
  1049  
  1050  	charsetArg, ok := args[1].(*Constant)
  1051  	if !ok {
  1052  		// `args[1]` is limited by BerolinaSQL to be a constant string,
  1053  		// should never go into here.
  1054  		return nil, errIncorrectArgs.GenWithStackByArgs("charset")
  1055  	}
  1056  	transcodingName := charsetArg.Value.GetString()
  1057  	bf.tp.Charset = strings.ToLower(transcodingName)
  1058  	// Quoted about the behavior of syntax CONVERT(expr, type) to CHAR():
  1059  	// In all cases, the string has the default defCauslation for the character set.
  1060  	// See https://dev.allegrosql.com/doc/refman/5.7/en/cast-functions.html#function_convert
  1061  	// Here in syntax CONVERT(expr USING transcoding_name), behavior is kept the same,
  1062  	// picking the default defCauslation of target charset.
  1063  	bf.tp.DefCauslate, err = charset.GetDefaultDefCauslation(bf.tp.Charset)
  1064  	if err != nil {
  1065  		return nil, errUnknownCharacterSet.GenWithStackByArgs(transcodingName)
  1066  	}
  1067  	// Result will be a binary string if converts charset to BINARY.
  1068  	// See https://dev.allegrosql.com/doc/refman/5.7/en/charset-binary-set.html
  1069  	if types.IsBinaryStr(bf.tp) {
  1070  		types.SetBinChsClnFlag(bf.tp)
  1071  	} else {
  1072  		bf.tp.Flag &= ^allegrosql.BinaryFlag
  1073  	}
  1074  
  1075  	bf.tp.Flen = allegrosql.MaxBlobWidth
  1076  	sig := &builtinConvertSig{bf}
  1077  	sig.setPbCode(fidelpb.ScalarFuncSig_Convert)
  1078  	return sig, nil
  1079  }
  1080  
  1081  type builtinConvertSig struct {
  1082  	baseBuiltinFunc
  1083  }
  1084  
  1085  func (b *builtinConvertSig) Clone() builtinFunc {
  1086  	newSig := &builtinConvertSig{}
  1087  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1088  	return newSig
  1089  }
  1090  
  1091  // evalString evals CONVERT(expr USING transcoding_name).
  1092  // Syntax CONVERT(expr, type) is parsed as cast expr so not handled here.
  1093  // See https://dev.allegrosql.com/doc/refman/5.7/en/cast-functions.html#function_convert
  1094  func (b *builtinConvertSig) evalString(event chunk.Event) (string, bool, error) {
  1095  	expr, isNull, err := b.args[0].EvalString(b.ctx, event)
  1096  	if isNull || err != nil {
  1097  		return "", true, err
  1098  	}
  1099  
  1100  	// Since charset is already validated and set from getFunction(), there's no
  1101  	// need to get charset from args again.
  1102  	encoding, _ := charset.Lookup(b.tp.Charset)
  1103  	// However, if `b.tp.Charset` is abnormally set to a wrong charset, we still
  1104  	// return with error.
  1105  	if encoding == nil {
  1106  		return "", true, errUnknownCharacterSet.GenWithStackByArgs(b.tp.Charset)
  1107  	}
  1108  
  1109  	target, _, err := transform.String(encoding.NewCausetDecoder(), expr)
  1110  	return target, err != nil, err
  1111  }
  1112  
  1113  type substringFunctionClass struct {
  1114  	baseFunctionClass
  1115  }
  1116  
  1117  func (c *substringFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  1118  	if err := c.verifyArgs(args); err != nil {
  1119  		return nil, err
  1120  	}
  1121  	argTps := []types.EvalType{types.ETString, types.ETInt}
  1122  	if len(args) == 3 {
  1123  		argTps = append(argTps, types.ETInt)
  1124  	}
  1125  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, argTps...)
  1126  	if err != nil {
  1127  		return nil, err
  1128  	}
  1129  
  1130  	argType := args[0].GetType()
  1131  	bf.tp.Flen = argType.Flen
  1132  	SetBinFlagOrBinStr(argType, bf.tp)
  1133  
  1134  	var sig builtinFunc
  1135  	switch {
  1136  	case len(args) == 3 && types.IsBinaryStr(argType):
  1137  		sig = &builtinSubstring3ArgsSig{bf}
  1138  		sig.setPbCode(fidelpb.ScalarFuncSig_Substring3Args)
  1139  	case len(args) == 3:
  1140  		sig = &builtinSubstring3ArgsUTF8Sig{bf}
  1141  		sig.setPbCode(fidelpb.ScalarFuncSig_Substring3ArgsUTF8)
  1142  	case len(args) == 2 && types.IsBinaryStr(argType):
  1143  		sig = &builtinSubstring2ArgsSig{bf}
  1144  		sig.setPbCode(fidelpb.ScalarFuncSig_Substring2Args)
  1145  	case len(args) == 2:
  1146  		sig = &builtinSubstring2ArgsUTF8Sig{bf}
  1147  		sig.setPbCode(fidelpb.ScalarFuncSig_Substring2ArgsUTF8)
  1148  	default:
  1149  		// Should never happens.
  1150  		return nil, errors.Errorf("SUBSTR invalid arg length, expect 2 or 3 but got: %v", len(args))
  1151  	}
  1152  	return sig, nil
  1153  }
  1154  
  1155  type builtinSubstring2ArgsSig struct {
  1156  	baseBuiltinFunc
  1157  }
  1158  
  1159  func (b *builtinSubstring2ArgsSig) Clone() builtinFunc {
  1160  	newSig := &builtinSubstring2ArgsSig{}
  1161  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1162  	return newSig
  1163  }
  1164  
  1165  // evalString evals SUBSTR(str,pos), SUBSTR(str FROM pos), SUBSTR() is a synonym for SUBSTRING().
  1166  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_substr
  1167  func (b *builtinSubstring2ArgsSig) evalString(event chunk.Event) (string, bool, error) {
  1168  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
  1169  	if isNull || err != nil {
  1170  		return "", true, err
  1171  	}
  1172  	pos, isNull, err := b.args[1].EvalInt(b.ctx, event)
  1173  	if isNull || err != nil {
  1174  		return "", true, err
  1175  	}
  1176  	length := int64(len(str))
  1177  	if pos < 0 {
  1178  		pos += length
  1179  	} else {
  1180  		pos--
  1181  	}
  1182  	if pos > length || pos < 0 {
  1183  		pos = length
  1184  	}
  1185  	return str[pos:], false, nil
  1186  }
  1187  
  1188  type builtinSubstring2ArgsUTF8Sig struct {
  1189  	baseBuiltinFunc
  1190  }
  1191  
  1192  func (b *builtinSubstring2ArgsUTF8Sig) Clone() builtinFunc {
  1193  	newSig := &builtinSubstring2ArgsUTF8Sig{}
  1194  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1195  	return newSig
  1196  }
  1197  
  1198  // evalString evals SUBSTR(str,pos), SUBSTR(str FROM pos), SUBSTR() is a synonym for SUBSTRING().
  1199  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_substr
  1200  func (b *builtinSubstring2ArgsUTF8Sig) evalString(event chunk.Event) (string, bool, error) {
  1201  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
  1202  	if isNull || err != nil {
  1203  		return "", true, err
  1204  	}
  1205  	pos, isNull, err := b.args[1].EvalInt(b.ctx, event)
  1206  	if isNull || err != nil {
  1207  		return "", true, err
  1208  	}
  1209  	runes := []rune(str)
  1210  	length := int64(len(runes))
  1211  	if pos < 0 {
  1212  		pos += length
  1213  	} else {
  1214  		pos--
  1215  	}
  1216  	if pos > length || pos < 0 {
  1217  		pos = length
  1218  	}
  1219  	return string(runes[pos:]), false, nil
  1220  }
  1221  
  1222  type builtinSubstring3ArgsSig struct {
  1223  	baseBuiltinFunc
  1224  }
  1225  
  1226  func (b *builtinSubstring3ArgsSig) Clone() builtinFunc {
  1227  	newSig := &builtinSubstring3ArgsSig{}
  1228  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1229  	return newSig
  1230  }
  1231  
  1232  // evalString evals SUBSTR(str,pos,len), SUBSTR(str FROM pos FOR len), SUBSTR() is a synonym for SUBSTRING().
  1233  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_substr
  1234  func (b *builtinSubstring3ArgsSig) evalString(event chunk.Event) (string, bool, error) {
  1235  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
  1236  	if isNull || err != nil {
  1237  		return "", true, err
  1238  	}
  1239  	pos, isNull, err := b.args[1].EvalInt(b.ctx, event)
  1240  	if isNull || err != nil {
  1241  		return "", true, err
  1242  	}
  1243  	length, isNull, err := b.args[2].EvalInt(b.ctx, event)
  1244  	if isNull || err != nil {
  1245  		return "", true, err
  1246  	}
  1247  	byteLen := int64(len(str))
  1248  	if pos < 0 {
  1249  		pos += byteLen
  1250  	} else {
  1251  		pos--
  1252  	}
  1253  	if pos > byteLen || pos < 0 {
  1254  		pos = byteLen
  1255  	}
  1256  	end := pos + length
  1257  	if end < pos {
  1258  		return "", false, nil
  1259  	} else if end < byteLen {
  1260  		return str[pos:end], false, nil
  1261  	}
  1262  	return str[pos:], false, nil
  1263  }
  1264  
  1265  type builtinSubstring3ArgsUTF8Sig struct {
  1266  	baseBuiltinFunc
  1267  }
  1268  
  1269  func (b *builtinSubstring3ArgsUTF8Sig) Clone() builtinFunc {
  1270  	newSig := &builtinSubstring3ArgsUTF8Sig{}
  1271  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1272  	return newSig
  1273  }
  1274  
  1275  // evalString evals SUBSTR(str,pos,len), SUBSTR(str FROM pos FOR len), SUBSTR() is a synonym for SUBSTRING().
  1276  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_substr
  1277  func (b *builtinSubstring3ArgsUTF8Sig) evalString(event chunk.Event) (string, bool, error) {
  1278  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
  1279  	if isNull || err != nil {
  1280  		return "", true, err
  1281  	}
  1282  	pos, isNull, err := b.args[1].EvalInt(b.ctx, event)
  1283  	if isNull || err != nil {
  1284  		return "", true, err
  1285  	}
  1286  	length, isNull, err := b.args[2].EvalInt(b.ctx, event)
  1287  	if isNull || err != nil {
  1288  		return "", true, err
  1289  	}
  1290  	runes := []rune(str)
  1291  	numRunes := int64(len(runes))
  1292  	if pos < 0 {
  1293  		pos += numRunes
  1294  	} else {
  1295  		pos--
  1296  	}
  1297  	if pos > numRunes || pos < 0 {
  1298  		pos = numRunes
  1299  	}
  1300  	end := pos + length
  1301  	if end < pos {
  1302  		return "", false, nil
  1303  	} else if end < numRunes {
  1304  		return string(runes[pos:end]), false, nil
  1305  	}
  1306  	return string(runes[pos:]), false, nil
  1307  }
  1308  
  1309  type substringIndexFunctionClass struct {
  1310  	baseFunctionClass
  1311  }
  1312  
  1313  func (c *substringIndexFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  1314  	if err := c.verifyArgs(args); err != nil {
  1315  		return nil, err
  1316  	}
  1317  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString, types.ETString, types.ETInt)
  1318  	if err != nil {
  1319  		return nil, err
  1320  	}
  1321  	argType := args[0].GetType()
  1322  	bf.tp.Flen = argType.Flen
  1323  	SetBinFlagOrBinStr(argType, bf.tp)
  1324  	sig := &builtinSubstringIndexSig{bf}
  1325  	sig.setPbCode(fidelpb.ScalarFuncSig_SubstringIndex)
  1326  	return sig, nil
  1327  }
  1328  
  1329  type builtinSubstringIndexSig struct {
  1330  	baseBuiltinFunc
  1331  }
  1332  
  1333  func (b *builtinSubstringIndexSig) Clone() builtinFunc {
  1334  	newSig := &builtinSubstringIndexSig{}
  1335  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1336  	return newSig
  1337  }
  1338  
  1339  // evalString evals a builtinSubstringIndexSig.
  1340  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_substring-index
  1341  func (b *builtinSubstringIndexSig) evalString(event chunk.Event) (d string, isNull bool, err error) {
  1342  	var (
  1343  		str, delim string
  1344  		count      int64
  1345  	)
  1346  	str, isNull, err = b.args[0].EvalString(b.ctx, event)
  1347  	if isNull || err != nil {
  1348  		return d, isNull, err
  1349  	}
  1350  	delim, isNull, err = b.args[1].EvalString(b.ctx, event)
  1351  	if isNull || err != nil {
  1352  		return d, isNull, err
  1353  	}
  1354  	count, isNull, err = b.args[2].EvalInt(b.ctx, event)
  1355  	if isNull || err != nil {
  1356  		return d, isNull, err
  1357  	}
  1358  	if len(delim) == 0 {
  1359  		return "", false, nil
  1360  	}
  1361  
  1362  	strs := strings.Split(str, delim)
  1363  	start, end := int64(0), int64(len(strs))
  1364  	if count > 0 {
  1365  		// If count is positive, everything to the left of the final delimiter (counting from the left) is returned.
  1366  		if count < end {
  1367  			end = count
  1368  		}
  1369  	} else {
  1370  		// If count is negative, everything to the right of the final delimiter (counting from the right) is returned.
  1371  		count = -count
  1372  		if count < 0 {
  1373  			// -count overflows max int64, returns an empty string.
  1374  			return "", false, nil
  1375  		}
  1376  
  1377  		if count < end {
  1378  			start = end - count
  1379  		}
  1380  	}
  1381  	substrs := strs[start:end]
  1382  	return strings.Join(substrs, delim), false, nil
  1383  }
  1384  
  1385  type locateFunctionClass struct {
  1386  	baseFunctionClass
  1387  }
  1388  
  1389  func (c *locateFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  1390  	if err := c.verifyArgs(args); err != nil {
  1391  		return nil, err
  1392  	}
  1393  	hasStartPos, argTps := len(args) == 3, []types.EvalType{types.ETString, types.ETString}
  1394  	if hasStartPos {
  1395  		argTps = append(argTps, types.ETInt)
  1396  	}
  1397  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, argTps...)
  1398  	if err != nil {
  1399  		return nil, err
  1400  	}
  1401  	var sig builtinFunc
  1402  	// Locate is multibyte safe.
  1403  	useBinary := bf.defCauslation == charset.DefCauslationBin
  1404  	switch {
  1405  	case hasStartPos && useBinary:
  1406  		sig = &builtinLocate3ArgsSig{bf}
  1407  		sig.setPbCode(fidelpb.ScalarFuncSig_Locate3Args)
  1408  	case hasStartPos:
  1409  		sig = &builtinLocate3ArgsUTF8Sig{bf}
  1410  		sig.setPbCode(fidelpb.ScalarFuncSig_Locate3ArgsUTF8)
  1411  	case useBinary:
  1412  		sig = &builtinLocate2ArgsSig{bf}
  1413  		sig.setPbCode(fidelpb.ScalarFuncSig_Locate2Args)
  1414  	default:
  1415  		sig = &builtinLocate2ArgsUTF8Sig{bf}
  1416  		sig.setPbCode(fidelpb.ScalarFuncSig_Locate2ArgsUTF8)
  1417  	}
  1418  	return sig, nil
  1419  }
  1420  
  1421  type builtinLocate2ArgsSig struct {
  1422  	baseBuiltinFunc
  1423  }
  1424  
  1425  func (b *builtinLocate2ArgsSig) Clone() builtinFunc {
  1426  	newSig := &builtinLocate2ArgsSig{}
  1427  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1428  	return newSig
  1429  }
  1430  
  1431  // evalInt evals LOCATE(substr,str), case-sensitive.
  1432  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_locate
  1433  func (b *builtinLocate2ArgsSig) evalInt(event chunk.Event) (int64, bool, error) {
  1434  	subStr, isNull, err := b.args[0].EvalString(b.ctx, event)
  1435  	if isNull || err != nil {
  1436  		return 0, isNull, err
  1437  	}
  1438  	str, isNull, err := b.args[1].EvalString(b.ctx, event)
  1439  	if isNull || err != nil {
  1440  		return 0, isNull, err
  1441  	}
  1442  	subStrLen := len(subStr)
  1443  	if subStrLen == 0 {
  1444  		return 1, false, nil
  1445  	}
  1446  	ret, idx := 0, strings.Index(str, subStr)
  1447  	if idx != -1 {
  1448  		ret = idx + 1
  1449  	}
  1450  	return int64(ret), false, nil
  1451  }
  1452  
  1453  type builtinLocate2ArgsUTF8Sig struct {
  1454  	baseBuiltinFunc
  1455  }
  1456  
  1457  func (b *builtinLocate2ArgsUTF8Sig) Clone() builtinFunc {
  1458  	newSig := &builtinLocate2ArgsUTF8Sig{}
  1459  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1460  	return newSig
  1461  }
  1462  
  1463  // evalInt evals LOCATE(substr,str).
  1464  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_locate
  1465  func (b *builtinLocate2ArgsUTF8Sig) evalInt(event chunk.Event) (int64, bool, error) {
  1466  	subStr, isNull, err := b.args[0].EvalString(b.ctx, event)
  1467  	if isNull || err != nil {
  1468  		return 0, isNull, err
  1469  	}
  1470  	str, isNull, err := b.args[1].EvalString(b.ctx, event)
  1471  	if isNull || err != nil {
  1472  		return 0, isNull, err
  1473  	}
  1474  	if int64(len([]rune(subStr))) == 0 {
  1475  		return 1, false, nil
  1476  	}
  1477  	if defCauslate.IsCIDefCauslation(b.defCauslation) {
  1478  		str = strings.ToLower(str)
  1479  		subStr = strings.ToLower(subStr)
  1480  	}
  1481  	ret, idx := 0, strings.Index(str, subStr)
  1482  	if idx != -1 {
  1483  		ret = utf8.RuneCountInString(str[:idx]) + 1
  1484  	}
  1485  	return int64(ret), false, nil
  1486  }
  1487  
  1488  type builtinLocate3ArgsSig struct {
  1489  	baseBuiltinFunc
  1490  }
  1491  
  1492  func (b *builtinLocate3ArgsSig) Clone() builtinFunc {
  1493  	newSig := &builtinLocate3ArgsSig{}
  1494  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1495  	return newSig
  1496  }
  1497  
  1498  // evalInt evals LOCATE(substr,str,pos), case-sensitive.
  1499  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_locate
  1500  func (b *builtinLocate3ArgsSig) evalInt(event chunk.Event) (int64, bool, error) {
  1501  	subStr, isNull, err := b.args[0].EvalString(b.ctx, event)
  1502  	if isNull || err != nil {
  1503  		return 0, isNull, err
  1504  	}
  1505  	str, isNull, err := b.args[1].EvalString(b.ctx, event)
  1506  	if isNull || err != nil {
  1507  		return 0, isNull, err
  1508  	}
  1509  	pos, isNull, err := b.args[2].EvalInt(b.ctx, event)
  1510  	// Transfer the argument which starts from 1 to real index which starts from 0.
  1511  	pos--
  1512  	if isNull || err != nil {
  1513  		return 0, isNull, err
  1514  	}
  1515  	subStrLen := len(subStr)
  1516  	if pos < 0 || pos > int64(len(str)-subStrLen) {
  1517  		return 0, false, nil
  1518  	} else if subStrLen == 0 {
  1519  		return pos + 1, false, nil
  1520  	}
  1521  	slice := str[pos:]
  1522  	idx := strings.Index(slice, subStr)
  1523  	if idx != -1 {
  1524  		return pos + int64(idx) + 1, false, nil
  1525  	}
  1526  	return 0, false, nil
  1527  }
  1528  
  1529  type builtinLocate3ArgsUTF8Sig struct {
  1530  	baseBuiltinFunc
  1531  }
  1532  
  1533  func (b *builtinLocate3ArgsUTF8Sig) Clone() builtinFunc {
  1534  	newSig := &builtinLocate3ArgsUTF8Sig{}
  1535  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1536  	return newSig
  1537  }
  1538  
  1539  // evalInt evals LOCATE(substr,str,pos).
  1540  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_locate
  1541  func (b *builtinLocate3ArgsUTF8Sig) evalInt(event chunk.Event) (int64, bool, error) {
  1542  	subStr, isNull, err := b.args[0].EvalString(b.ctx, event)
  1543  	if isNull || err != nil {
  1544  		return 0, isNull, err
  1545  	}
  1546  	str, isNull, err := b.args[1].EvalString(b.ctx, event)
  1547  	if isNull || err != nil {
  1548  		return 0, isNull, err
  1549  	}
  1550  	if defCauslate.IsCIDefCauslation(b.defCauslation) {
  1551  		subStr = strings.ToLower(subStr)
  1552  		str = strings.ToLower(str)
  1553  	}
  1554  	pos, isNull, err := b.args[2].EvalInt(b.ctx, event)
  1555  	// Transfer the argument which starts from 1 to real index which starts from 0.
  1556  	pos--
  1557  	if isNull || err != nil {
  1558  		return 0, isNull, err
  1559  	}
  1560  	subStrLen := len([]rune(subStr))
  1561  	if pos < 0 || pos > int64(len([]rune(str))-subStrLen) {
  1562  		return 0, false, nil
  1563  	} else if subStrLen == 0 {
  1564  		return pos + 1, false, nil
  1565  	}
  1566  	slice := string([]rune(str)[pos:])
  1567  	idx := strings.Index(slice, subStr)
  1568  	if idx != -1 {
  1569  		return pos + int64(utf8.RuneCountInString(slice[:idx])) + 1, false, nil
  1570  	}
  1571  	return 0, false, nil
  1572  }
  1573  
  1574  type hexFunctionClass struct {
  1575  	baseFunctionClass
  1576  }
  1577  
  1578  func (c *hexFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  1579  	if err := c.verifyArgs(args); err != nil {
  1580  		return nil, err
  1581  	}
  1582  
  1583  	argTp := args[0].GetType().EvalType()
  1584  	switch argTp {
  1585  	case types.ETString, types.ETDatetime, types.ETTimestamp, types.ETDuration, types.ETJson:
  1586  		bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString)
  1587  		if err != nil {
  1588  			return nil, err
  1589  		}
  1590  		bf.tp.Charset, bf.tp.DefCauslate = ctx.GetStochastikVars().GetCharsetInfo()
  1591  		// Use UTF-8 as default
  1592  		bf.tp.Flen = args[0].GetType().Flen * 3 * 2
  1593  		sig := &builtinHexStrArgSig{bf}
  1594  		sig.setPbCode(fidelpb.ScalarFuncSig_HexStrArg)
  1595  		return sig, nil
  1596  	case types.ETInt, types.ETReal, types.ETDecimal:
  1597  		bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETInt)
  1598  		if err != nil {
  1599  			return nil, err
  1600  		}
  1601  		bf.tp.Flen = args[0].GetType().Flen * 2
  1602  		bf.tp.Charset, bf.tp.DefCauslate = ctx.GetStochastikVars().GetCharsetInfo()
  1603  		sig := &builtinHexIntArgSig{bf}
  1604  		sig.setPbCode(fidelpb.ScalarFuncSig_HexIntArg)
  1605  		return sig, nil
  1606  	default:
  1607  		return nil, errors.Errorf("Hex invalid args, need int or string but get %T", args[0].GetType())
  1608  	}
  1609  }
  1610  
  1611  type builtinHexStrArgSig struct {
  1612  	baseBuiltinFunc
  1613  }
  1614  
  1615  func (b *builtinHexStrArgSig) Clone() builtinFunc {
  1616  	newSig := &builtinHexStrArgSig{}
  1617  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1618  	return newSig
  1619  }
  1620  
  1621  // evalString evals a builtinHexStrArgSig, corresponding to hex(str)
  1622  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_hex
  1623  func (b *builtinHexStrArgSig) evalString(event chunk.Event) (string, bool, error) {
  1624  	d, isNull, err := b.args[0].EvalString(b.ctx, event)
  1625  	if isNull || err != nil {
  1626  		return d, isNull, err
  1627  	}
  1628  	return strings.ToUpper(hex.EncodeToString(replog.Slice(d))), false, nil
  1629  }
  1630  
  1631  type builtinHexIntArgSig struct {
  1632  	baseBuiltinFunc
  1633  }
  1634  
  1635  func (b *builtinHexIntArgSig) Clone() builtinFunc {
  1636  	newSig := &builtinHexIntArgSig{}
  1637  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1638  	return newSig
  1639  }
  1640  
  1641  // evalString evals a builtinHexIntArgSig, corresponding to hex(N)
  1642  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_hex
  1643  func (b *builtinHexIntArgSig) evalString(event chunk.Event) (string, bool, error) {
  1644  	x, isNull, err := b.args[0].EvalInt(b.ctx, event)
  1645  	if isNull || err != nil {
  1646  		return "", isNull, err
  1647  	}
  1648  	return strings.ToUpper(fmt.Sprintf("%x", uint64(x))), false, nil
  1649  }
  1650  
  1651  type unhexFunctionClass struct {
  1652  	baseFunctionClass
  1653  }
  1654  
  1655  func (c *unhexFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  1656  	if err := c.verifyArgs(args); err != nil {
  1657  		return nil, err
  1658  	}
  1659  	var retFlen int
  1660  
  1661  	if err := c.verifyArgs(args); err != nil {
  1662  		return nil, err
  1663  	}
  1664  	argType := args[0].GetType()
  1665  	argEvalTp := argType.EvalType()
  1666  	switch argEvalTp {
  1667  	case types.ETString, types.ETDatetime, types.ETTimestamp, types.ETDuration, types.ETJson:
  1668  		// Use UTF-8 as default charset, so there're (Flen * 3 + 1) / 2 byte-pairs
  1669  		retFlen = (argType.Flen*3 + 1) / 2
  1670  	case types.ETInt, types.ETReal, types.ETDecimal:
  1671  		// For number value, there're (Flen + 1) / 2 byte-pairs
  1672  		retFlen = (argType.Flen + 1) / 2
  1673  	default:
  1674  		return nil, errors.Errorf("Unhex invalid args, need int or string but get %s", argType)
  1675  	}
  1676  
  1677  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString)
  1678  	if err != nil {
  1679  		return nil, err
  1680  	}
  1681  	bf.tp.Flen = retFlen
  1682  	types.SetBinChsClnFlag(bf.tp)
  1683  	sig := &builtinUnHexSig{bf}
  1684  	sig.setPbCode(fidelpb.ScalarFuncSig_UnHex)
  1685  	return sig, nil
  1686  }
  1687  
  1688  type builtinUnHexSig struct {
  1689  	baseBuiltinFunc
  1690  }
  1691  
  1692  func (b *builtinUnHexSig) Clone() builtinFunc {
  1693  	newSig := &builtinUnHexSig{}
  1694  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1695  	return newSig
  1696  }
  1697  
  1698  // evalString evals a builtinUnHexSig.
  1699  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_unhex
  1700  func (b *builtinUnHexSig) evalString(event chunk.Event) (string, bool, error) {
  1701  	var bs []byte
  1702  
  1703  	d, isNull, err := b.args[0].EvalString(b.ctx, event)
  1704  	if isNull || err != nil {
  1705  		return d, isNull, err
  1706  	}
  1707  	// Add a '0' to the front, if the length is not the multiple of 2
  1708  	if len(d)%2 != 0 {
  1709  		d = "0" + d
  1710  	}
  1711  	bs, err = hex.DecodeString(d)
  1712  	if err != nil {
  1713  		return "", true, nil
  1714  	}
  1715  	return string(bs), false, nil
  1716  }
  1717  
  1718  const spaceChars = " "
  1719  
  1720  type trimFunctionClass struct {
  1721  	baseFunctionClass
  1722  }
  1723  
  1724  // getFunction sets trim built-in function signature.
  1725  // The syntax of trim in allegrosql is 'TRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str), TRIM([remstr FROM] str)',
  1726  // but we wil convert it into trim(str), trim(str, remstr) and trim(str, remstr, direction) in AST.
  1727  func (c *trimFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  1728  	if err := c.verifyArgs(args); err != nil {
  1729  		return nil, err
  1730  	}
  1731  
  1732  	switch len(args) {
  1733  	case 1:
  1734  		bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString)
  1735  		if err != nil {
  1736  			return nil, err
  1737  		}
  1738  		argType := args[0].GetType()
  1739  		bf.tp.Flen = argType.Flen
  1740  		SetBinFlagOrBinStr(argType, bf.tp)
  1741  		sig := &builtinTrim1ArgSig{bf}
  1742  		sig.setPbCode(fidelpb.ScalarFuncSig_Trim1Arg)
  1743  		return sig, nil
  1744  
  1745  	case 2:
  1746  		bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString, types.ETString)
  1747  		if err != nil {
  1748  			return nil, err
  1749  		}
  1750  		argType := args[0].GetType()
  1751  		SetBinFlagOrBinStr(argType, bf.tp)
  1752  		sig := &builtinTrim2ArgsSig{bf}
  1753  		sig.setPbCode(fidelpb.ScalarFuncSig_Trim2Args)
  1754  		return sig, nil
  1755  
  1756  	case 3:
  1757  		bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString, types.ETString, types.ETInt)
  1758  		if err != nil {
  1759  			return nil, err
  1760  		}
  1761  		argType := args[0].GetType()
  1762  		bf.tp.Flen = argType.Flen
  1763  		SetBinFlagOrBinStr(argType, bf.tp)
  1764  		sig := &builtinTrim3ArgsSig{bf}
  1765  		sig.setPbCode(fidelpb.ScalarFuncSig_Trim3Args)
  1766  		return sig, nil
  1767  
  1768  	default:
  1769  		return nil, c.verifyArgs(args)
  1770  	}
  1771  }
  1772  
  1773  type builtinTrim1ArgSig struct {
  1774  	baseBuiltinFunc
  1775  }
  1776  
  1777  func (b *builtinTrim1ArgSig) Clone() builtinFunc {
  1778  	newSig := &builtinTrim1ArgSig{}
  1779  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1780  	return newSig
  1781  }
  1782  
  1783  // evalString evals a builtinTrim1ArgSig, corresponding to trim(str)
  1784  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_trim
  1785  func (b *builtinTrim1ArgSig) evalString(event chunk.Event) (d string, isNull bool, err error) {
  1786  	d, isNull, err = b.args[0].EvalString(b.ctx, event)
  1787  	if isNull || err != nil {
  1788  		return d, isNull, err
  1789  	}
  1790  	return strings.Trim(d, spaceChars), false, nil
  1791  }
  1792  
  1793  type builtinTrim2ArgsSig struct {
  1794  	baseBuiltinFunc
  1795  }
  1796  
  1797  func (b *builtinTrim2ArgsSig) Clone() builtinFunc {
  1798  	newSig := &builtinTrim2ArgsSig{}
  1799  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1800  	return newSig
  1801  }
  1802  
  1803  // evalString evals a builtinTrim2ArgsSig, corresponding to trim(str, remstr)
  1804  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_trim
  1805  func (b *builtinTrim2ArgsSig) evalString(event chunk.Event) (d string, isNull bool, err error) {
  1806  	var str, remstr string
  1807  
  1808  	str, isNull, err = b.args[0].EvalString(b.ctx, event)
  1809  	if isNull || err != nil {
  1810  		return d, isNull, err
  1811  	}
  1812  	remstr, isNull, err = b.args[1].EvalString(b.ctx, event)
  1813  	if isNull || err != nil {
  1814  		return d, isNull, err
  1815  	}
  1816  	d = trimLeft(str, remstr)
  1817  	d = trimRight(d, remstr)
  1818  	return d, false, nil
  1819  }
  1820  
  1821  type builtinTrim3ArgsSig struct {
  1822  	baseBuiltinFunc
  1823  }
  1824  
  1825  func (b *builtinTrim3ArgsSig) Clone() builtinFunc {
  1826  	newSig := &builtinTrim3ArgsSig{}
  1827  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1828  	return newSig
  1829  }
  1830  
  1831  // evalString evals a builtinTrim3ArgsSig, corresponding to trim(str, remstr, direction)
  1832  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_trim
  1833  func (b *builtinTrim3ArgsSig) evalString(event chunk.Event) (d string, isNull bool, err error) {
  1834  	var (
  1835  		str, remstr  string
  1836  		x            int64
  1837  		direction    ast.TrimDirectionType
  1838  		isRemStrNull bool
  1839  	)
  1840  	str, isNull, err = b.args[0].EvalString(b.ctx, event)
  1841  	if isNull || err != nil {
  1842  		return d, isNull, err
  1843  	}
  1844  	remstr, isRemStrNull, err = b.args[1].EvalString(b.ctx, event)
  1845  	if err != nil {
  1846  		return d, isNull, err
  1847  	}
  1848  	x, isNull, err = b.args[2].EvalInt(b.ctx, event)
  1849  	if isNull || err != nil {
  1850  		return d, isNull, err
  1851  	}
  1852  	direction = ast.TrimDirectionType(x)
  1853  	if direction == ast.TrimLeading {
  1854  		if isRemStrNull {
  1855  			d = strings.TrimLeft(str, spaceChars)
  1856  		} else {
  1857  			d = trimLeft(str, remstr)
  1858  		}
  1859  	} else if direction == ast.TrimTrailing {
  1860  		if isRemStrNull {
  1861  			d = strings.TrimRight(str, spaceChars)
  1862  		} else {
  1863  			d = trimRight(str, remstr)
  1864  		}
  1865  	} else {
  1866  		if isRemStrNull {
  1867  			d = strings.Trim(str, spaceChars)
  1868  		} else {
  1869  			d = trimLeft(str, remstr)
  1870  			d = trimRight(d, remstr)
  1871  		}
  1872  	}
  1873  	return d, false, nil
  1874  }
  1875  
  1876  type lTrimFunctionClass struct {
  1877  	baseFunctionClass
  1878  }
  1879  
  1880  func (c *lTrimFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  1881  	if err := c.verifyArgs(args); err != nil {
  1882  		return nil, err
  1883  	}
  1884  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString)
  1885  	if err != nil {
  1886  		return nil, err
  1887  	}
  1888  	argType := args[0].GetType()
  1889  	bf.tp.Flen = argType.Flen
  1890  	SetBinFlagOrBinStr(argType, bf.tp)
  1891  	sig := &builtinLTrimSig{bf}
  1892  	sig.setPbCode(fidelpb.ScalarFuncSig_LTrim)
  1893  	return sig, nil
  1894  }
  1895  
  1896  type builtinLTrimSig struct {
  1897  	baseBuiltinFunc
  1898  }
  1899  
  1900  func (b *builtinLTrimSig) Clone() builtinFunc {
  1901  	newSig := &builtinLTrimSig{}
  1902  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1903  	return newSig
  1904  }
  1905  
  1906  // evalString evals a builtinLTrimSig
  1907  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_ltrim
  1908  func (b *builtinLTrimSig) evalString(event chunk.Event) (d string, isNull bool, err error) {
  1909  	d, isNull, err = b.args[0].EvalString(b.ctx, event)
  1910  	if isNull || err != nil {
  1911  		return d, isNull, err
  1912  	}
  1913  	return strings.TrimLeft(d, spaceChars), false, nil
  1914  }
  1915  
  1916  type rTrimFunctionClass struct {
  1917  	baseFunctionClass
  1918  }
  1919  
  1920  func (c *rTrimFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  1921  	if err := c.verifyArgs(args); err != nil {
  1922  		return nil, err
  1923  	}
  1924  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString)
  1925  	if err != nil {
  1926  		return nil, err
  1927  	}
  1928  	argType := args[0].GetType()
  1929  	bf.tp.Flen = argType.Flen
  1930  	SetBinFlagOrBinStr(argType, bf.tp)
  1931  	sig := &builtinRTrimSig{bf}
  1932  	sig.setPbCode(fidelpb.ScalarFuncSig_RTrim)
  1933  	return sig, nil
  1934  }
  1935  
  1936  type builtinRTrimSig struct {
  1937  	baseBuiltinFunc
  1938  }
  1939  
  1940  func (b *builtinRTrimSig) Clone() builtinFunc {
  1941  	newSig := &builtinRTrimSig{}
  1942  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1943  	return newSig
  1944  }
  1945  
  1946  // evalString evals a builtinRTrimSig
  1947  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_rtrim
  1948  func (b *builtinRTrimSig) evalString(event chunk.Event) (d string, isNull bool, err error) {
  1949  	d, isNull, err = b.args[0].EvalString(b.ctx, event)
  1950  	if isNull || err != nil {
  1951  		return d, isNull, err
  1952  	}
  1953  	return strings.TrimRight(d, spaceChars), false, nil
  1954  }
  1955  
  1956  func trimLeft(str, remstr string) string {
  1957  	for {
  1958  		x := strings.TrimPrefix(str, remstr)
  1959  		if len(x) == len(str) {
  1960  			return x
  1961  		}
  1962  		str = x
  1963  	}
  1964  }
  1965  
  1966  func trimRight(str, remstr string) string {
  1967  	for {
  1968  		x := strings.TrimSuffix(str, remstr)
  1969  		if len(x) == len(str) {
  1970  			return x
  1971  		}
  1972  		str = x
  1973  	}
  1974  }
  1975  
  1976  func getFlen4LpadAndRpad(ctx stochastikctx.Context, arg Expression) int {
  1977  	if constant, ok := arg.(*Constant); ok {
  1978  		length, isNull, err := constant.EvalInt(ctx, chunk.Event{})
  1979  		if err != nil {
  1980  			logutil.BgLogger().Error("eval `Flen` for LPAD/RPAD", zap.Error(err))
  1981  		}
  1982  		if isNull || err != nil || length > allegrosql.MaxBlobWidth {
  1983  			return allegrosql.MaxBlobWidth
  1984  		}
  1985  		return int(length)
  1986  	}
  1987  	return allegrosql.MaxBlobWidth
  1988  }
  1989  
  1990  type lpadFunctionClass struct {
  1991  	baseFunctionClass
  1992  }
  1993  
  1994  func (c *lpadFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  1995  	if err := c.verifyArgs(args); err != nil {
  1996  		return nil, err
  1997  	}
  1998  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString, types.ETInt, types.ETString)
  1999  	if err != nil {
  2000  		return nil, err
  2001  	}
  2002  	bf.tp.Flen = getFlen4LpadAndRpad(bf.ctx, args[1])
  2003  	SetBinFlagOrBinStr(args[0].GetType(), bf.tp)
  2004  	SetBinFlagOrBinStr(args[2].GetType(), bf.tp)
  2005  
  2006  	valStr, _ := ctx.GetStochastikVars().GetSystemVar(variable.MaxAllowedPacket)
  2007  	maxAllowedPacket, err := strconv.ParseUint(valStr, 10, 64)
  2008  	if err != nil {
  2009  		return nil, errors.Trace(err)
  2010  	}
  2011  
  2012  	if types.IsBinaryStr(args[0].GetType()) || types.IsBinaryStr(args[2].GetType()) {
  2013  		sig := &builtinLpadSig{bf, maxAllowedPacket}
  2014  		sig.setPbCode(fidelpb.ScalarFuncSig_Lpad)
  2015  		return sig, nil
  2016  	}
  2017  	if bf.tp.Flen *= 4; bf.tp.Flen > allegrosql.MaxBlobWidth {
  2018  		bf.tp.Flen = allegrosql.MaxBlobWidth
  2019  	}
  2020  	sig := &builtinLpadUTF8Sig{bf, maxAllowedPacket}
  2021  	sig.setPbCode(fidelpb.ScalarFuncSig_LpadUTF8)
  2022  	return sig, nil
  2023  }
  2024  
  2025  type builtinLpadSig struct {
  2026  	baseBuiltinFunc
  2027  	maxAllowedPacket uint64
  2028  }
  2029  
  2030  func (b *builtinLpadSig) Clone() builtinFunc {
  2031  	newSig := &builtinLpadSig{}
  2032  	newSig.cloneFrom(&b.baseBuiltinFunc)
  2033  	newSig.maxAllowedPacket = b.maxAllowedPacket
  2034  	return newSig
  2035  }
  2036  
  2037  // evalString evals LPAD(str,len,padstr).
  2038  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_lpad
  2039  func (b *builtinLpadSig) evalString(event chunk.Event) (string, bool, error) {
  2040  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
  2041  	if isNull || err != nil {
  2042  		return "", true, err
  2043  	}
  2044  	byteLength := len(str)
  2045  
  2046  	length, isNull, err := b.args[1].EvalInt(b.ctx, event)
  2047  	if isNull || err != nil {
  2048  		return "", true, err
  2049  	}
  2050  	targetLength := int(length)
  2051  
  2052  	if uint64(targetLength) > b.maxAllowedPacket {
  2053  		b.ctx.GetStochastikVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("lpad", b.maxAllowedPacket))
  2054  		return "", true, nil
  2055  	}
  2056  
  2057  	padStr, isNull, err := b.args[2].EvalString(b.ctx, event)
  2058  	if isNull || err != nil {
  2059  		return "", true, err
  2060  	}
  2061  	padLength := len(padStr)
  2062  
  2063  	if targetLength < 0 || targetLength > b.tp.Flen || (byteLength < targetLength && padLength == 0) {
  2064  		return "", true, nil
  2065  	}
  2066  
  2067  	if tailLen := targetLength - byteLength; tailLen > 0 {
  2068  		repeatCount := tailLen/padLength + 1
  2069  		str = strings.Repeat(padStr, repeatCount)[:tailLen] + str
  2070  	}
  2071  	return str[:targetLength], false, nil
  2072  }
  2073  
  2074  type builtinLpadUTF8Sig struct {
  2075  	baseBuiltinFunc
  2076  	maxAllowedPacket uint64
  2077  }
  2078  
  2079  func (b *builtinLpadUTF8Sig) Clone() builtinFunc {
  2080  	newSig := &builtinLpadUTF8Sig{}
  2081  	newSig.cloneFrom(&b.baseBuiltinFunc)
  2082  	newSig.maxAllowedPacket = b.maxAllowedPacket
  2083  	return newSig
  2084  }
  2085  
  2086  // evalString evals LPAD(str,len,padstr).
  2087  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_lpad
  2088  func (b *builtinLpadUTF8Sig) evalString(event chunk.Event) (string, bool, error) {
  2089  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
  2090  	if isNull || err != nil {
  2091  		return "", true, err
  2092  	}
  2093  	runeLength := len([]rune(str))
  2094  
  2095  	length, isNull, err := b.args[1].EvalInt(b.ctx, event)
  2096  	if isNull || err != nil {
  2097  		return "", true, err
  2098  	}
  2099  	targetLength := int(length)
  2100  
  2101  	if uint64(targetLength)*uint64(allegrosql.MaxBytesOfCharacter) > b.maxAllowedPacket {
  2102  		b.ctx.GetStochastikVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("lpad", b.maxAllowedPacket))
  2103  		return "", true, nil
  2104  	}
  2105  
  2106  	padStr, isNull, err := b.args[2].EvalString(b.ctx, event)
  2107  	if isNull || err != nil {
  2108  		return "", true, err
  2109  	}
  2110  	padLength := len([]rune(padStr))
  2111  
  2112  	if targetLength < 0 || targetLength*4 > b.tp.Flen || (runeLength < targetLength && padLength == 0) {
  2113  		return "", true, nil
  2114  	}
  2115  
  2116  	if tailLen := targetLength - runeLength; tailLen > 0 {
  2117  		repeatCount := tailLen/padLength + 1
  2118  		str = string([]rune(strings.Repeat(padStr, repeatCount))[:tailLen]) + str
  2119  	}
  2120  	return string([]rune(str)[:targetLength]), false, nil
  2121  }
  2122  
  2123  type rpadFunctionClass struct {
  2124  	baseFunctionClass
  2125  }
  2126  
  2127  func (c *rpadFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  2128  	if err := c.verifyArgs(args); err != nil {
  2129  		return nil, err
  2130  	}
  2131  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString, types.ETInt, types.ETString)
  2132  	if err != nil {
  2133  		return nil, err
  2134  	}
  2135  	bf.tp.Flen = getFlen4LpadAndRpad(bf.ctx, args[1])
  2136  	SetBinFlagOrBinStr(args[0].GetType(), bf.tp)
  2137  	SetBinFlagOrBinStr(args[2].GetType(), bf.tp)
  2138  
  2139  	valStr, _ := ctx.GetStochastikVars().GetSystemVar(variable.MaxAllowedPacket)
  2140  	maxAllowedPacket, err := strconv.ParseUint(valStr, 10, 64)
  2141  	if err != nil {
  2142  		return nil, errors.Trace(err)
  2143  	}
  2144  
  2145  	if types.IsBinaryStr(args[0].GetType()) || types.IsBinaryStr(args[2].GetType()) {
  2146  		sig := &builtinRpadSig{bf, maxAllowedPacket}
  2147  		sig.setPbCode(fidelpb.ScalarFuncSig_Rpad)
  2148  		return sig, nil
  2149  	}
  2150  	if bf.tp.Flen *= 4; bf.tp.Flen > allegrosql.MaxBlobWidth {
  2151  		bf.tp.Flen = allegrosql.MaxBlobWidth
  2152  	}
  2153  	sig := &builtinRpadUTF8Sig{bf, maxAllowedPacket}
  2154  	sig.setPbCode(fidelpb.ScalarFuncSig_RpadUTF8)
  2155  	return sig, nil
  2156  }
  2157  
  2158  type builtinRpadSig struct {
  2159  	baseBuiltinFunc
  2160  	maxAllowedPacket uint64
  2161  }
  2162  
  2163  func (b *builtinRpadSig) Clone() builtinFunc {
  2164  	newSig := &builtinRpadSig{}
  2165  	newSig.cloneFrom(&b.baseBuiltinFunc)
  2166  	newSig.maxAllowedPacket = b.maxAllowedPacket
  2167  	return newSig
  2168  }
  2169  
  2170  // evalString evals RPAD(str,len,padstr).
  2171  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_rpad
  2172  func (b *builtinRpadSig) evalString(event chunk.Event) (string, bool, error) {
  2173  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
  2174  	if isNull || err != nil {
  2175  		return "", true, err
  2176  	}
  2177  	byteLength := len(str)
  2178  
  2179  	length, isNull, err := b.args[1].EvalInt(b.ctx, event)
  2180  	if isNull || err != nil {
  2181  		return "", true, err
  2182  	}
  2183  	targetLength := int(length)
  2184  	if uint64(targetLength) > b.maxAllowedPacket {
  2185  		b.ctx.GetStochastikVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("rpad", b.maxAllowedPacket))
  2186  		return "", true, nil
  2187  	}
  2188  
  2189  	padStr, isNull, err := b.args[2].EvalString(b.ctx, event)
  2190  	if isNull || err != nil {
  2191  		return "", true, err
  2192  	}
  2193  	padLength := len(padStr)
  2194  
  2195  	if targetLength < 0 || targetLength > b.tp.Flen || (byteLength < targetLength && padLength == 0) {
  2196  		return "", true, nil
  2197  	}
  2198  
  2199  	if tailLen := targetLength - byteLength; tailLen > 0 {
  2200  		repeatCount := tailLen/padLength + 1
  2201  		str = str + strings.Repeat(padStr, repeatCount)
  2202  	}
  2203  	return str[:targetLength], false, nil
  2204  }
  2205  
  2206  type builtinRpadUTF8Sig struct {
  2207  	baseBuiltinFunc
  2208  	maxAllowedPacket uint64
  2209  }
  2210  
  2211  func (b *builtinRpadUTF8Sig) Clone() builtinFunc {
  2212  	newSig := &builtinRpadUTF8Sig{}
  2213  	newSig.cloneFrom(&b.baseBuiltinFunc)
  2214  	newSig.maxAllowedPacket = b.maxAllowedPacket
  2215  	return newSig
  2216  }
  2217  
  2218  // evalString evals RPAD(str,len,padstr).
  2219  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_rpad
  2220  func (b *builtinRpadUTF8Sig) evalString(event chunk.Event) (string, bool, error) {
  2221  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
  2222  	if isNull || err != nil {
  2223  		return "", true, err
  2224  	}
  2225  	runeLength := len([]rune(str))
  2226  
  2227  	length, isNull, err := b.args[1].EvalInt(b.ctx, event)
  2228  	if isNull || err != nil {
  2229  		return "", true, err
  2230  	}
  2231  	targetLength := int(length)
  2232  
  2233  	if uint64(targetLength)*uint64(allegrosql.MaxBytesOfCharacter) > b.maxAllowedPacket {
  2234  		b.ctx.GetStochastikVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("rpad", b.maxAllowedPacket))
  2235  		return "", true, nil
  2236  	}
  2237  
  2238  	padStr, isNull, err := b.args[2].EvalString(b.ctx, event)
  2239  	if isNull || err != nil {
  2240  		return "", true, err
  2241  	}
  2242  	padLength := len([]rune(padStr))
  2243  
  2244  	if targetLength < 0 || targetLength*4 > b.tp.Flen || (runeLength < targetLength && padLength == 0) {
  2245  		return "", true, nil
  2246  	}
  2247  
  2248  	if tailLen := targetLength - runeLength; tailLen > 0 {
  2249  		repeatCount := tailLen/padLength + 1
  2250  		str = str + strings.Repeat(padStr, repeatCount)
  2251  	}
  2252  	return string([]rune(str)[:targetLength]), false, nil
  2253  }
  2254  
  2255  type bitLengthFunctionClass struct {
  2256  	baseFunctionClass
  2257  }
  2258  
  2259  func (c *bitLengthFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  2260  	if err := c.verifyArgs(args); err != nil {
  2261  		return nil, err
  2262  	}
  2263  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETString)
  2264  	if err != nil {
  2265  		return nil, err
  2266  	}
  2267  	bf.tp.Flen = 10
  2268  	sig := &builtinBitLengthSig{bf}
  2269  	sig.setPbCode(fidelpb.ScalarFuncSig_BitLength)
  2270  	return sig, nil
  2271  }
  2272  
  2273  type builtinBitLengthSig struct {
  2274  	baseBuiltinFunc
  2275  }
  2276  
  2277  func (b *builtinBitLengthSig) Clone() builtinFunc {
  2278  	newSig := &builtinBitLengthSig{}
  2279  	newSig.cloneFrom(&b.baseBuiltinFunc)
  2280  	return newSig
  2281  }
  2282  
  2283  // evalInt evaluates a builtinBitLengthSig.
  2284  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_bit-length
  2285  func (b *builtinBitLengthSig) evalInt(event chunk.Event) (int64, bool, error) {
  2286  	val, isNull, err := b.args[0].EvalString(b.ctx, event)
  2287  	if isNull || err != nil {
  2288  		return 0, isNull, err
  2289  	}
  2290  
  2291  	return int64(len(val) * 8), false, nil
  2292  }
  2293  
  2294  type charFunctionClass struct {
  2295  	baseFunctionClass
  2296  }
  2297  
  2298  func (c *charFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  2299  	if err := c.verifyArgs(args); err != nil {
  2300  		return nil, err
  2301  	}
  2302  	argTps := make([]types.EvalType, 0, len(args))
  2303  	for i := 0; i < len(args)-1; i++ {
  2304  		argTps = append(argTps, types.ETInt)
  2305  	}
  2306  	argTps = append(argTps, types.ETString)
  2307  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, argTps...)
  2308  	if err != nil {
  2309  		return nil, err
  2310  	}
  2311  	// The last argument represents the charset name after "using".
  2312  	if _, ok := args[len(args)-1].(*Constant); !ok {
  2313  		// If we got there, there must be something wrong in other places.
  2314  		logutil.BgLogger().Warn(fmt.Sprintf("The last argument in char function must be constant, but got %T", args[len(args)-1]))
  2315  		return nil, errIncorrectArgs
  2316  	}
  2317  	charsetName, isNull, err := args[len(args)-1].EvalString(ctx, chunk.Event{})
  2318  	if err != nil {
  2319  		return nil, err
  2320  	}
  2321  	if isNull {
  2322  		// Use the default charset binary if it is nil.
  2323  		bf.tp.Charset, bf.tp.DefCauslate = charset.CharsetBin, charset.DefCauslationBin
  2324  		bf.tp.Flag |= allegrosql.BinaryFlag
  2325  	} else {
  2326  		bf.tp.Charset = charsetName
  2327  		defaultDefCauslate, err := charset.GetDefaultDefCauslation(charsetName)
  2328  		if err != nil {
  2329  			return nil, err
  2330  		}
  2331  		bf.tp.DefCauslate = defaultDefCauslate
  2332  	}
  2333  	bf.tp.Flen = 4 * (len(args) - 1)
  2334  
  2335  	sig := &builtinCharSig{bf}
  2336  	sig.setPbCode(fidelpb.ScalarFuncSig_Char)
  2337  	return sig, nil
  2338  }
  2339  
  2340  type builtinCharSig struct {
  2341  	baseBuiltinFunc
  2342  }
  2343  
  2344  func (b *builtinCharSig) Clone() builtinFunc {
  2345  	newSig := &builtinCharSig{}
  2346  	newSig.cloneFrom(&b.baseBuiltinFunc)
  2347  	return newSig
  2348  }
  2349  
  2350  func (b *builtinCharSig) convertToBytes(ints []int64) []byte {
  2351  	buffer := bytes.NewBuffer([]byte{})
  2352  	for i := len(ints) - 1; i >= 0; i-- {
  2353  		for count, val := 0, ints[i]; count < 4; count++ {
  2354  			buffer.WriteByte(byte(val & 0xff))
  2355  			if val >>= 8; val == 0 {
  2356  				break
  2357  			}
  2358  		}
  2359  	}
  2360  	return reverseBytes(buffer.Bytes())
  2361  }
  2362  
  2363  // evalString evals CHAR(N,... [USING charset_name]).
  2364  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_char.
  2365  func (b *builtinCharSig) evalString(event chunk.Event) (string, bool, error) {
  2366  	bigints := make([]int64, 0, len(b.args)-1)
  2367  
  2368  	for i := 0; i < len(b.args)-1; i++ {
  2369  		val, IsNull, err := b.args[i].EvalInt(b.ctx, event)
  2370  		if err != nil {
  2371  			return "", true, err
  2372  		}
  2373  		if IsNull {
  2374  			continue
  2375  		}
  2376  		bigints = append(bigints, val)
  2377  	}
  2378  	result := string(b.convertToBytes(bigints))
  2379  	return result, false, nil
  2380  }
  2381  
  2382  type charLengthFunctionClass struct {
  2383  	baseFunctionClass
  2384  }
  2385  
  2386  func (c *charLengthFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  2387  	if argsErr := c.verifyArgs(args); argsErr != nil {
  2388  		return nil, argsErr
  2389  	}
  2390  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETString)
  2391  	if err != nil {
  2392  		return nil, err
  2393  	}
  2394  	if types.IsBinaryStr(args[0].GetType()) {
  2395  		sig := &builtinCharLengthBinarySig{bf}
  2396  		sig.setPbCode(fidelpb.ScalarFuncSig_CharLength)
  2397  		return sig, nil
  2398  	}
  2399  	sig := &builtinCharLengthUTF8Sig{bf}
  2400  	sig.setPbCode(fidelpb.ScalarFuncSig_CharLengthUTF8)
  2401  	return sig, nil
  2402  }
  2403  
  2404  type builtinCharLengthBinarySig struct {
  2405  	baseBuiltinFunc
  2406  }
  2407  
  2408  func (b *builtinCharLengthBinarySig) Clone() builtinFunc {
  2409  	newSig := &builtinCharLengthBinarySig{}
  2410  	newSig.cloneFrom(&b.baseBuiltinFunc)
  2411  	return newSig
  2412  }
  2413  
  2414  // evalInt evals a builtinCharLengthUTF8Sig for binary string type.
  2415  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_char-length
  2416  func (b *builtinCharLengthBinarySig) evalInt(event chunk.Event) (int64, bool, error) {
  2417  	val, isNull, err := b.args[0].EvalString(b.ctx, event)
  2418  	if isNull || err != nil {
  2419  		return 0, isNull, err
  2420  	}
  2421  	return int64(len(val)), false, nil
  2422  }
  2423  
  2424  type builtinCharLengthUTF8Sig struct {
  2425  	baseBuiltinFunc
  2426  }
  2427  
  2428  func (b *builtinCharLengthUTF8Sig) Clone() builtinFunc {
  2429  	newSig := &builtinCharLengthUTF8Sig{}
  2430  	newSig.cloneFrom(&b.baseBuiltinFunc)
  2431  	return newSig
  2432  }
  2433  
  2434  // evalInt evals a builtinCharLengthUTF8Sig for non-binary string type.
  2435  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_char-length
  2436  func (b *builtinCharLengthUTF8Sig) evalInt(event chunk.Event) (int64, bool, error) {
  2437  	val, isNull, err := b.args[0].EvalString(b.ctx, event)
  2438  	if isNull || err != nil {
  2439  		return 0, isNull, err
  2440  	}
  2441  	return int64(len([]rune(val))), false, nil
  2442  }
  2443  
  2444  type findInSetFunctionClass struct {
  2445  	baseFunctionClass
  2446  }
  2447  
  2448  func (c *findInSetFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  2449  	if err := c.verifyArgs(args); err != nil {
  2450  		return nil, err
  2451  	}
  2452  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETString, types.ETString)
  2453  	if err != nil {
  2454  		return nil, err
  2455  	}
  2456  	bf.tp.Flen = 3
  2457  	sig := &builtinFindInSetSig{bf}
  2458  	sig.setPbCode(fidelpb.ScalarFuncSig_FindInSet)
  2459  	return sig, nil
  2460  }
  2461  
  2462  type builtinFindInSetSig struct {
  2463  	baseBuiltinFunc
  2464  }
  2465  
  2466  func (b *builtinFindInSetSig) Clone() builtinFunc {
  2467  	newSig := &builtinFindInSetSig{}
  2468  	newSig.cloneFrom(&b.baseBuiltinFunc)
  2469  	return newSig
  2470  }
  2471  
  2472  // evalInt evals FIND_IN_SET(str,strlist).
  2473  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_find-in-set
  2474  // TODO: This function can be optimized by using bit arithmetic when the first argument is
  2475  // a constant string and the second is a defCausumn of type SET.
  2476  func (b *builtinFindInSetSig) evalInt(event chunk.Event) (int64, bool, error) {
  2477  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
  2478  	if isNull || err != nil {
  2479  		return 0, isNull, err
  2480  	}
  2481  
  2482  	strlist, isNull, err := b.args[1].EvalString(b.ctx, event)
  2483  	if isNull || err != nil {
  2484  		return 0, isNull, err
  2485  	}
  2486  
  2487  	if len(strlist) == 0 {
  2488  		return 0, false, nil
  2489  	}
  2490  
  2491  	for i, strInSet := range strings.Split(strlist, ",") {
  2492  		if b.ctor.Compare(str, strInSet) == 0 {
  2493  			return int64(i + 1), false, nil
  2494  		}
  2495  	}
  2496  	return 0, false, nil
  2497  }
  2498  
  2499  type fieldFunctionClass struct {
  2500  	baseFunctionClass
  2501  }
  2502  
  2503  func (c *fieldFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  2504  	if err := c.verifyArgs(args); err != nil {
  2505  		return nil, err
  2506  	}
  2507  
  2508  	isAllString, isAllNumber := true, true
  2509  	for i, length := 0, len(args); i < length; i++ {
  2510  		argTp := args[i].GetType().EvalType()
  2511  		isAllString = isAllString && (argTp == types.ETString)
  2512  		isAllNumber = isAllNumber && (argTp == types.ETInt)
  2513  	}
  2514  
  2515  	argTps := make([]types.EvalType, len(args))
  2516  	argTp := types.ETReal
  2517  	if isAllString {
  2518  		argTp = types.ETString
  2519  	} else if isAllNumber {
  2520  		argTp = types.ETInt
  2521  	}
  2522  	for i, length := 0, len(args); i < length; i++ {
  2523  		argTps[i] = argTp
  2524  	}
  2525  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, argTps...)
  2526  	if err != nil {
  2527  		return nil, err
  2528  	}
  2529  	var sig builtinFunc
  2530  	switch argTp {
  2531  	case types.ETReal:
  2532  		sig = &builtinFieldRealSig{bf}
  2533  		sig.setPbCode(fidelpb.ScalarFuncSig_FieldReal)
  2534  	case types.ETInt:
  2535  		sig = &builtinFieldIntSig{bf}
  2536  		sig.setPbCode(fidelpb.ScalarFuncSig_FieldInt)
  2537  	case types.ETString:
  2538  		sig = &builtinFieldStringSig{bf}
  2539  		sig.setPbCode(fidelpb.ScalarFuncSig_FieldString)
  2540  	}
  2541  	return sig, nil
  2542  }
  2543  
  2544  type builtinFieldIntSig struct {
  2545  	baseBuiltinFunc
  2546  }
  2547  
  2548  func (b *builtinFieldIntSig) Clone() builtinFunc {
  2549  	newSig := &builtinFieldIntSig{}
  2550  	newSig.cloneFrom(&b.baseBuiltinFunc)
  2551  	return newSig
  2552  }
  2553  
  2554  // evalInt evals FIELD(str,str1,str2,str3,...).
  2555  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_field
  2556  func (b *builtinFieldIntSig) evalInt(event chunk.Event) (int64, bool, error) {
  2557  	str, isNull, err := b.args[0].EvalInt(b.ctx, event)
  2558  	if isNull || err != nil {
  2559  		return 0, err != nil, err
  2560  	}
  2561  	for i, length := 1, len(b.args); i < length; i++ {
  2562  		stri, isNull, err := b.args[i].EvalInt(b.ctx, event)
  2563  		if err != nil {
  2564  			return 0, true, err
  2565  		}
  2566  		if !isNull && str == stri {
  2567  			return int64(i), false, nil
  2568  		}
  2569  	}
  2570  	return 0, false, nil
  2571  }
  2572  
  2573  type builtinFieldRealSig struct {
  2574  	baseBuiltinFunc
  2575  }
  2576  
  2577  func (b *builtinFieldRealSig) Clone() builtinFunc {
  2578  	newSig := &builtinFieldRealSig{}
  2579  	newSig.cloneFrom(&b.baseBuiltinFunc)
  2580  	return newSig
  2581  }
  2582  
  2583  // evalInt evals FIELD(str,str1,str2,str3,...).
  2584  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_field
  2585  func (b *builtinFieldRealSig) evalInt(event chunk.Event) (int64, bool, error) {
  2586  	str, isNull, err := b.args[0].EvalReal(b.ctx, event)
  2587  	if isNull || err != nil {
  2588  		return 0, err != nil, err
  2589  	}
  2590  	for i, length := 1, len(b.args); i < length; i++ {
  2591  		stri, isNull, err := b.args[i].EvalReal(b.ctx, event)
  2592  		if err != nil {
  2593  			return 0, true, err
  2594  		}
  2595  		if !isNull && str == stri {
  2596  			return int64(i), false, nil
  2597  		}
  2598  	}
  2599  	return 0, false, nil
  2600  }
  2601  
  2602  type builtinFieldStringSig struct {
  2603  	baseBuiltinFunc
  2604  }
  2605  
  2606  func (b *builtinFieldStringSig) Clone() builtinFunc {
  2607  	newSig := &builtinFieldStringSig{}
  2608  	newSig.cloneFrom(&b.baseBuiltinFunc)
  2609  	return newSig
  2610  }
  2611  
  2612  // evalInt evals FIELD(str,str1,str2,str3,...).
  2613  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_field
  2614  func (b *builtinFieldStringSig) evalInt(event chunk.Event) (int64, bool, error) {
  2615  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
  2616  	if isNull || err != nil {
  2617  		return 0, err != nil, err
  2618  	}
  2619  	for i, length := 1, len(b.args); i < length; i++ {
  2620  		stri, isNull, err := b.args[i].EvalString(b.ctx, event)
  2621  		if err != nil {
  2622  			return 0, true, err
  2623  		}
  2624  		if !isNull && b.ctor.Compare(str, stri) == 0 {
  2625  			return int64(i), false, nil
  2626  		}
  2627  	}
  2628  	return 0, false, nil
  2629  }
  2630  
  2631  type makeSetFunctionClass struct {
  2632  	baseFunctionClass
  2633  }
  2634  
  2635  func (c *makeSetFunctionClass) getFlen(ctx stochastikctx.Context, args []Expression) int {
  2636  	flen, count := 0, 0
  2637  	if constant, ok := args[0].(*Constant); ok {
  2638  		bits, isNull, err := constant.EvalInt(ctx, chunk.Event{})
  2639  		if err == nil && !isNull {
  2640  			for i, length := 1, len(args); i < length; i++ {
  2641  				if (bits & (1 << uint(i-1))) != 0 {
  2642  					flen += args[i].GetType().Flen
  2643  					count++
  2644  				}
  2645  			}
  2646  			if count > 0 {
  2647  				flen += count - 1
  2648  			}
  2649  			return flen
  2650  		}
  2651  	}
  2652  	for i, length := 1, len(args); i < length; i++ {
  2653  		flen += args[i].GetType().Flen
  2654  	}
  2655  	return flen + len(args) - 1 - 1
  2656  }
  2657  
  2658  func (c *makeSetFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  2659  	if err := c.verifyArgs(args); err != nil {
  2660  		return nil, err
  2661  	}
  2662  	argTps := make([]types.EvalType, len(args))
  2663  	argTps[0] = types.ETInt
  2664  	for i, length := 1, len(args); i < length; i++ {
  2665  		argTps[i] = types.ETString
  2666  	}
  2667  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, argTps...)
  2668  	if err != nil {
  2669  		return nil, err
  2670  	}
  2671  	for i, length := 0, len(args); i < length; i++ {
  2672  		SetBinFlagOrBinStr(args[i].GetType(), bf.tp)
  2673  	}
  2674  	bf.tp.Flen = c.getFlen(bf.ctx, args)
  2675  	if bf.tp.Flen > allegrosql.MaxBlobWidth {
  2676  		bf.tp.Flen = allegrosql.MaxBlobWidth
  2677  	}
  2678  	sig := &builtinMakeSetSig{bf}
  2679  	sig.setPbCode(fidelpb.ScalarFuncSig_MakeSet)
  2680  	return sig, nil
  2681  }
  2682  
  2683  type builtinMakeSetSig struct {
  2684  	baseBuiltinFunc
  2685  }
  2686  
  2687  func (b *builtinMakeSetSig) Clone() builtinFunc {
  2688  	newSig := &builtinMakeSetSig{}
  2689  	newSig.cloneFrom(&b.baseBuiltinFunc)
  2690  	return newSig
  2691  }
  2692  
  2693  // evalString evals MAKE_SET(bits,str1,str2,...).
  2694  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_make-set
  2695  func (b *builtinMakeSetSig) evalString(event chunk.Event) (string, bool, error) {
  2696  	bits, isNull, err := b.args[0].EvalInt(b.ctx, event)
  2697  	if isNull || err != nil {
  2698  		return "", true, err
  2699  	}
  2700  
  2701  	sets := make([]string, 0, len(b.args)-1)
  2702  	for i, length := 1, len(b.args); i < length; i++ {
  2703  		if (bits & (1 << uint(i-1))) == 0 {
  2704  			continue
  2705  		}
  2706  		str, isNull, err := b.args[i].EvalString(b.ctx, event)
  2707  		if err != nil {
  2708  			return "", true, err
  2709  		}
  2710  		if !isNull {
  2711  			sets = append(sets, str)
  2712  		}
  2713  	}
  2714  
  2715  	return strings.Join(sets, ","), false, nil
  2716  }
  2717  
  2718  type octFunctionClass struct {
  2719  	baseFunctionClass
  2720  }
  2721  
  2722  func (c *octFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  2723  	if err := c.verifyArgs(args); err != nil {
  2724  		return nil, err
  2725  	}
  2726  	var sig builtinFunc
  2727  	if IsBinaryLiteral(args[0]) || args[0].GetType().EvalType() == types.ETInt {
  2728  		bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETInt)
  2729  		if err != nil {
  2730  			return nil, err
  2731  		}
  2732  		bf.tp.Charset, bf.tp.DefCauslate = ctx.GetStochastikVars().GetCharsetInfo()
  2733  		bf.tp.Flen, bf.tp.Decimal = 64, types.UnspecifiedLength
  2734  		sig = &builtinOctIntSig{bf}
  2735  		sig.setPbCode(fidelpb.ScalarFuncSig_OctInt)
  2736  	} else {
  2737  		bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString)
  2738  		if err != nil {
  2739  			return nil, err
  2740  		}
  2741  		bf.tp.Charset, bf.tp.DefCauslate = ctx.GetStochastikVars().GetCharsetInfo()
  2742  		bf.tp.Flen, bf.tp.Decimal = 64, types.UnspecifiedLength
  2743  		sig = &builtinOctStringSig{bf}
  2744  		sig.setPbCode(fidelpb.ScalarFuncSig_OctString)
  2745  	}
  2746  
  2747  	return sig, nil
  2748  }
  2749  
  2750  type builtinOctIntSig struct {
  2751  	baseBuiltinFunc
  2752  }
  2753  
  2754  func (b *builtinOctIntSig) Clone() builtinFunc {
  2755  	newSig := &builtinOctIntSig{}
  2756  	newSig.cloneFrom(&b.baseBuiltinFunc)
  2757  	return newSig
  2758  }
  2759  
  2760  // evalString evals OCT(N).
  2761  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_oct
  2762  func (b *builtinOctIntSig) evalString(event chunk.Event) (string, bool, error) {
  2763  	val, isNull, err := b.args[0].EvalInt(b.ctx, event)
  2764  	if isNull || err != nil {
  2765  		return "", isNull, err
  2766  	}
  2767  
  2768  	return strconv.FormatUint(uint64(val), 8), false, nil
  2769  }
  2770  
  2771  type builtinOctStringSig struct {
  2772  	baseBuiltinFunc
  2773  }
  2774  
  2775  func (b *builtinOctStringSig) Clone() builtinFunc {
  2776  	newSig := &builtinOctStringSig{}
  2777  	newSig.cloneFrom(&b.baseBuiltinFunc)
  2778  	return newSig
  2779  }
  2780  
  2781  // evalString evals OCT(N).
  2782  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_oct
  2783  func (b *builtinOctStringSig) evalString(event chunk.Event) (string, bool, error) {
  2784  	val, isNull, err := b.args[0].EvalString(b.ctx, event)
  2785  	if isNull || err != nil {
  2786  		return "", isNull, err
  2787  	}
  2788  
  2789  	negative, overflow := false, false
  2790  	val = getValidPrefix(strings.TrimSpace(val), 10)
  2791  	if len(val) == 0 {
  2792  		return "0", false, nil
  2793  	}
  2794  
  2795  	if val[0] == '-' {
  2796  		negative, val = true, val[1:]
  2797  	}
  2798  	numVal, err := strconv.ParseUint(val, 10, 64)
  2799  	if err != nil {
  2800  		numError, ok := err.(*strconv.NumError)
  2801  		if !ok || numError.Err != strconv.ErrRange {
  2802  			return "", true, errors.Trace(err)
  2803  		}
  2804  		overflow = true
  2805  	}
  2806  	if negative && !overflow {
  2807  		numVal = -numVal
  2808  	}
  2809  	return strconv.FormatUint(numVal, 8), false, nil
  2810  }
  2811  
  2812  type ordFunctionClass struct {
  2813  	baseFunctionClass
  2814  }
  2815  
  2816  func (c *ordFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  2817  	if err := c.verifyArgs(args); err != nil {
  2818  		return nil, err
  2819  	}
  2820  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETString)
  2821  	if err != nil {
  2822  		return nil, err
  2823  	}
  2824  	bf.tp.Flen = 10
  2825  	sig := &builtinOrdSig{bf}
  2826  	sig.setPbCode(fidelpb.ScalarFuncSig_Ord)
  2827  	return sig, nil
  2828  }
  2829  
  2830  type builtinOrdSig struct {
  2831  	baseBuiltinFunc
  2832  }
  2833  
  2834  func (b *builtinOrdSig) Clone() builtinFunc {
  2835  	newSig := &builtinOrdSig{}
  2836  	newSig.cloneFrom(&b.baseBuiltinFunc)
  2837  	return newSig
  2838  }
  2839  
  2840  // evalInt evals a builtinOrdSig.
  2841  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_ord
  2842  func (b *builtinOrdSig) evalInt(event chunk.Event) (int64, bool, error) {
  2843  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
  2844  	if isNull || err != nil {
  2845  		return 0, isNull, err
  2846  	}
  2847  
  2848  	ord, err := chooseOrdFunc(b.args[0].GetType().Charset)
  2849  	if err != nil {
  2850  		return 0, false, err
  2851  	}
  2852  	return ord(str), false, nil
  2853  }
  2854  
  2855  func chooseOrdFunc(charSet string) (func(string) int64, error) {
  2856  	// use utf8 by default
  2857  	if charSet == "" {
  2858  		charSet = charset.CharsetUTF8
  2859  	}
  2860  	desc, err := charset.GetCharsetDesc(charSet)
  2861  	if err != nil {
  2862  		return nil, err
  2863  	}
  2864  	if desc.Maxlen == 1 {
  2865  		return ordSingleByte, nil
  2866  	}
  2867  	return ordUtf8, nil
  2868  }
  2869  
  2870  func ordSingleByte(str string) int64 {
  2871  	if len(str) == 0 {
  2872  		return 0
  2873  	}
  2874  	return int64(str[0])
  2875  }
  2876  
  2877  func ordUtf8(str string) int64 {
  2878  	if len(str) == 0 {
  2879  		return 0
  2880  	}
  2881  	_, size := utf8.DecodeRuneInString(str)
  2882  	leftMost := str[:size]
  2883  	var result int64
  2884  	var factor int64 = 1
  2885  	for i := len(leftMost) - 1; i >= 0; i-- {
  2886  		result += int64(leftMost[i]) * factor
  2887  		factor *= 256
  2888  	}
  2889  	return result
  2890  }
  2891  
  2892  type quoteFunctionClass struct {
  2893  	baseFunctionClass
  2894  }
  2895  
  2896  func (c *quoteFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  2897  	if err := c.verifyArgs(args); err != nil {
  2898  		return nil, err
  2899  	}
  2900  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString)
  2901  	if err != nil {
  2902  		return nil, err
  2903  	}
  2904  	SetBinFlagOrBinStr(args[0].GetType(), bf.tp)
  2905  	bf.tp.Flen = 2*args[0].GetType().Flen + 2
  2906  	if bf.tp.Flen > allegrosql.MaxBlobWidth {
  2907  		bf.tp.Flen = allegrosql.MaxBlobWidth
  2908  	}
  2909  	sig := &builtinQuoteSig{bf}
  2910  	sig.setPbCode(fidelpb.ScalarFuncSig_Quote)
  2911  	return sig, nil
  2912  }
  2913  
  2914  type builtinQuoteSig struct {
  2915  	baseBuiltinFunc
  2916  }
  2917  
  2918  func (b *builtinQuoteSig) Clone() builtinFunc {
  2919  	newSig := &builtinQuoteSig{}
  2920  	newSig.cloneFrom(&b.baseBuiltinFunc)
  2921  	return newSig
  2922  }
  2923  
  2924  // evalString evals QUOTE(str).
  2925  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_quote
  2926  func (b *builtinQuoteSig) evalString(event chunk.Event) (string, bool, error) {
  2927  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
  2928  	if err != nil {
  2929  		return "", true, err
  2930  	} else if isNull {
  2931  		// If the argument is NULL, the return value is the word "NULL" without enclosing single quotation marks. see ref.
  2932  		return "NULL", false, err
  2933  	}
  2934  
  2935  	return Quote(str), false, nil
  2936  }
  2937  
  2938  // Quote produce a result that can be used as a properly escaped data value in an ALLEGROALLEGROSQL memex.
  2939  func Quote(str string) string {
  2940  	runes := []rune(str)
  2941  	buffer := bytes.NewBufferString("")
  2942  	buffer.WriteRune('\'')
  2943  	for i, runeLength := 0, len(runes); i < runeLength; i++ {
  2944  		switch runes[i] {
  2945  		case '\\', '\'':
  2946  			buffer.WriteRune('\\')
  2947  			buffer.WriteRune(runes[i])
  2948  		case 0:
  2949  			buffer.WriteRune('\\')
  2950  			buffer.WriteRune('0')
  2951  		case '\032':
  2952  			buffer.WriteRune('\\')
  2953  			buffer.WriteRune('Z')
  2954  		default:
  2955  			buffer.WriteRune(runes[i])
  2956  		}
  2957  	}
  2958  	buffer.WriteRune('\'')
  2959  
  2960  	return buffer.String()
  2961  }
  2962  
  2963  type binFunctionClass struct {
  2964  	baseFunctionClass
  2965  }
  2966  
  2967  func (c *binFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  2968  	if err := c.verifyArgs(args); err != nil {
  2969  		return nil, err
  2970  	}
  2971  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETInt)
  2972  	if err != nil {
  2973  		return nil, err
  2974  	}
  2975  	bf.tp.Charset, bf.tp.DefCauslate = ctx.GetStochastikVars().GetCharsetInfo()
  2976  	bf.tp.Flen = 64
  2977  	sig := &builtinBinSig{bf}
  2978  	sig.setPbCode(fidelpb.ScalarFuncSig_Bin)
  2979  	return sig, nil
  2980  }
  2981  
  2982  type builtinBinSig struct {
  2983  	baseBuiltinFunc
  2984  }
  2985  
  2986  func (b *builtinBinSig) Clone() builtinFunc {
  2987  	newSig := &builtinBinSig{}
  2988  	newSig.cloneFrom(&b.baseBuiltinFunc)
  2989  	return newSig
  2990  }
  2991  
  2992  // evalString evals BIN(N).
  2993  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_bin
  2994  func (b *builtinBinSig) evalString(event chunk.Event) (string, bool, error) {
  2995  	val, isNull, err := b.args[0].EvalInt(b.ctx, event)
  2996  	if isNull || err != nil {
  2997  		return "", true, err
  2998  	}
  2999  	return fmt.Sprintf("%b", uint64(val)), false, nil
  3000  }
  3001  
  3002  type eltFunctionClass struct {
  3003  	baseFunctionClass
  3004  }
  3005  
  3006  func (c *eltFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  3007  	if argsErr := c.verifyArgs(args); argsErr != nil {
  3008  		return nil, argsErr
  3009  	}
  3010  	argTps := make([]types.EvalType, 0, len(args))
  3011  	argTps = append(argTps, types.ETInt)
  3012  	for i := 1; i < len(args); i++ {
  3013  		argTps = append(argTps, types.ETString)
  3014  	}
  3015  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, argTps...)
  3016  	if err != nil {
  3017  		return nil, err
  3018  	}
  3019  	for _, arg := range args[1:] {
  3020  		argType := arg.GetType()
  3021  		if types.IsBinaryStr(argType) {
  3022  			types.SetBinChsClnFlag(bf.tp)
  3023  		}
  3024  		if argType.Flen > bf.tp.Flen {
  3025  			bf.tp.Flen = argType.Flen
  3026  		}
  3027  	}
  3028  	sig := &builtinEltSig{bf}
  3029  	sig.setPbCode(fidelpb.ScalarFuncSig_Elt)
  3030  	return sig, nil
  3031  }
  3032  
  3033  type builtinEltSig struct {
  3034  	baseBuiltinFunc
  3035  }
  3036  
  3037  func (b *builtinEltSig) Clone() builtinFunc {
  3038  	newSig := &builtinEltSig{}
  3039  	newSig.cloneFrom(&b.baseBuiltinFunc)
  3040  	return newSig
  3041  }
  3042  
  3043  // evalString evals a ELT(N,str1,str2,str3,...).
  3044  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_elt
  3045  func (b *builtinEltSig) evalString(event chunk.Event) (string, bool, error) {
  3046  	idx, isNull, err := b.args[0].EvalInt(b.ctx, event)
  3047  	if isNull || err != nil {
  3048  		return "", true, err
  3049  	}
  3050  	if idx < 1 || idx >= int64(len(b.args)) {
  3051  		return "", true, nil
  3052  	}
  3053  	arg, isNull, err := b.args[idx].EvalString(b.ctx, event)
  3054  	if isNull || err != nil {
  3055  		return "", true, err
  3056  	}
  3057  	return arg, false, nil
  3058  }
  3059  
  3060  type exportSetFunctionClass struct {
  3061  	baseFunctionClass
  3062  }
  3063  
  3064  func (c *exportSetFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) {
  3065  	if err = c.verifyArgs(args); err != nil {
  3066  		return nil, err
  3067  	}
  3068  	argTps := make([]types.EvalType, 0, 5)
  3069  	argTps = append(argTps, types.ETInt, types.ETString, types.ETString)
  3070  	if len(args) > 3 {
  3071  		argTps = append(argTps, types.ETString)
  3072  	}
  3073  	if len(args) > 4 {
  3074  		argTps = append(argTps, types.ETInt)
  3075  	}
  3076  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, argTps...)
  3077  	if err != nil {
  3078  		return nil, err
  3079  	}
  3080  	bf.tp.Flen = allegrosql.MaxBlobWidth
  3081  	switch len(args) {
  3082  	case 3:
  3083  		sig = &builtinExportSet3ArgSig{bf}
  3084  		sig.setPbCode(fidelpb.ScalarFuncSig_ExportSet3Arg)
  3085  	case 4:
  3086  		sig = &builtinExportSet4ArgSig{bf}
  3087  		sig.setPbCode(fidelpb.ScalarFuncSig_ExportSet4Arg)
  3088  	case 5:
  3089  		sig = &builtinExportSet5ArgSig{bf}
  3090  		sig.setPbCode(fidelpb.ScalarFuncSig_ExportSet5Arg)
  3091  	}
  3092  	return sig, nil
  3093  }
  3094  
  3095  // exportSet evals EXPORT_SET(bits,on,off,separator,number_of_bits).
  3096  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_export-set
  3097  func exportSet(bits int64, on, off, separator string, numberOfBits int64) string {
  3098  	result := ""
  3099  	for i := uint64(0); i < uint64(numberOfBits); i++ {
  3100  		if (bits & (1 << i)) > 0 {
  3101  			result += on
  3102  		} else {
  3103  			result += off
  3104  		}
  3105  		if i < uint64(numberOfBits)-1 {
  3106  			result += separator
  3107  		}
  3108  	}
  3109  	return result
  3110  }
  3111  
  3112  type builtinExportSet3ArgSig struct {
  3113  	baseBuiltinFunc
  3114  }
  3115  
  3116  func (b *builtinExportSet3ArgSig) Clone() builtinFunc {
  3117  	newSig := &builtinExportSet3ArgSig{}
  3118  	newSig.cloneFrom(&b.baseBuiltinFunc)
  3119  	return newSig
  3120  }
  3121  
  3122  // evalString evals EXPORT_SET(bits,on,off).
  3123  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_export-set
  3124  func (b *builtinExportSet3ArgSig) evalString(event chunk.Event) (string, bool, error) {
  3125  	bits, isNull, err := b.args[0].EvalInt(b.ctx, event)
  3126  	if isNull || err != nil {
  3127  		return "", true, err
  3128  	}
  3129  
  3130  	on, isNull, err := b.args[1].EvalString(b.ctx, event)
  3131  	if isNull || err != nil {
  3132  		return "", true, err
  3133  	}
  3134  
  3135  	off, isNull, err := b.args[2].EvalString(b.ctx, event)
  3136  	if isNull || err != nil {
  3137  		return "", true, err
  3138  	}
  3139  
  3140  	return exportSet(bits, on, off, ",", 64), false, nil
  3141  }
  3142  
  3143  type builtinExportSet4ArgSig struct {
  3144  	baseBuiltinFunc
  3145  }
  3146  
  3147  func (b *builtinExportSet4ArgSig) Clone() builtinFunc {
  3148  	newSig := &builtinExportSet4ArgSig{}
  3149  	newSig.cloneFrom(&b.baseBuiltinFunc)
  3150  	return newSig
  3151  }
  3152  
  3153  // evalString evals EXPORT_SET(bits,on,off,separator).
  3154  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_export-set
  3155  func (b *builtinExportSet4ArgSig) evalString(event chunk.Event) (string, bool, error) {
  3156  	bits, isNull, err := b.args[0].EvalInt(b.ctx, event)
  3157  	if isNull || err != nil {
  3158  		return "", true, err
  3159  	}
  3160  
  3161  	on, isNull, err := b.args[1].EvalString(b.ctx, event)
  3162  	if isNull || err != nil {
  3163  		return "", true, err
  3164  	}
  3165  
  3166  	off, isNull, err := b.args[2].EvalString(b.ctx, event)
  3167  	if isNull || err != nil {
  3168  		return "", true, err
  3169  	}
  3170  
  3171  	separator, isNull, err := b.args[3].EvalString(b.ctx, event)
  3172  	if isNull || err != nil {
  3173  		return "", true, err
  3174  	}
  3175  
  3176  	return exportSet(bits, on, off, separator, 64), false, nil
  3177  }
  3178  
  3179  type builtinExportSet5ArgSig struct {
  3180  	baseBuiltinFunc
  3181  }
  3182  
  3183  func (b *builtinExportSet5ArgSig) Clone() builtinFunc {
  3184  	newSig := &builtinExportSet5ArgSig{}
  3185  	newSig.cloneFrom(&b.baseBuiltinFunc)
  3186  	return newSig
  3187  }
  3188  
  3189  // evalString evals EXPORT_SET(bits,on,off,separator,number_of_bits).
  3190  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_export-set
  3191  func (b *builtinExportSet5ArgSig) evalString(event chunk.Event) (string, bool, error) {
  3192  	bits, isNull, err := b.args[0].EvalInt(b.ctx, event)
  3193  	if isNull || err != nil {
  3194  		return "", true, err
  3195  	}
  3196  
  3197  	on, isNull, err := b.args[1].EvalString(b.ctx, event)
  3198  	if isNull || err != nil {
  3199  		return "", true, err
  3200  	}
  3201  
  3202  	off, isNull, err := b.args[2].EvalString(b.ctx, event)
  3203  	if isNull || err != nil {
  3204  		return "", true, err
  3205  	}
  3206  
  3207  	separator, isNull, err := b.args[3].EvalString(b.ctx, event)
  3208  	if isNull || err != nil {
  3209  		return "", true, err
  3210  	}
  3211  
  3212  	numberOfBits, isNull, err := b.args[4].EvalInt(b.ctx, event)
  3213  	if isNull || err != nil {
  3214  		return "", true, err
  3215  	}
  3216  	if numberOfBits < 0 || numberOfBits > 64 {
  3217  		numberOfBits = 64
  3218  	}
  3219  
  3220  	return exportSet(bits, on, off, separator, numberOfBits), false, nil
  3221  }
  3222  
  3223  type formatFunctionClass struct {
  3224  	baseFunctionClass
  3225  }
  3226  
  3227  func (c *formatFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  3228  	if err := c.verifyArgs(args); err != nil {
  3229  		return nil, err
  3230  	}
  3231  	argTps := make([]types.EvalType, 2, 3)
  3232  	argTps[1] = types.ETInt
  3233  	argTp := args[0].GetType().EvalType()
  3234  	if argTp == types.ETDecimal || argTp == types.ETInt {
  3235  		argTps[0] = types.ETDecimal
  3236  	} else {
  3237  		argTps[0] = types.ETReal
  3238  	}
  3239  	if len(args) == 3 {
  3240  		argTps = append(argTps, types.ETString)
  3241  	}
  3242  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, argTps...)
  3243  	if err != nil {
  3244  		return nil, err
  3245  	}
  3246  	bf.tp.Charset, bf.tp.DefCauslate = ctx.GetStochastikVars().GetCharsetInfo()
  3247  	bf.tp.Flen = allegrosql.MaxBlobWidth
  3248  	var sig builtinFunc
  3249  	if len(args) == 3 {
  3250  		sig = &builtinFormatWithLocaleSig{bf}
  3251  		sig.setPbCode(fidelpb.ScalarFuncSig_FormatWithLocale)
  3252  	} else {
  3253  		sig = &builtinFormatSig{bf}
  3254  		sig.setPbCode(fidelpb.ScalarFuncSig_Format)
  3255  	}
  3256  	return sig, nil
  3257  }
  3258  
  3259  // formatMaxDecimals limits the maximum number of decimal digits for result of
  3260  // function `format`, this value is same as `FORMAT_MAX_DECIMALS` in MyALLEGROSQL source code.
  3261  const formatMaxDecimals int64 = 30
  3262  
  3263  // evalNumDecArgsForFormat evaluates first 2 arguments, i.e, x and d, for function `format`.
  3264  func evalNumDecArgsForFormat(f builtinFunc, event chunk.Event) (string, string, bool, error) {
  3265  	var xStr string
  3266  	arg0, arg1 := f.getArgs()[0], f.getArgs()[1]
  3267  	ctx := f.getCtx()
  3268  	if arg0.GetType().EvalType() == types.ETDecimal {
  3269  		x, isNull, err := arg0.EvalDecimal(ctx, event)
  3270  		if isNull || err != nil {
  3271  			return "", "", isNull, err
  3272  		}
  3273  		xStr = x.String()
  3274  	} else {
  3275  		x, isNull, err := arg0.EvalReal(ctx, event)
  3276  		if isNull || err != nil {
  3277  			return "", "", isNull, err
  3278  		}
  3279  		xStr = strconv.FormatFloat(x, 'f', -1, 64)
  3280  	}
  3281  	d, isNull, err := arg1.EvalInt(ctx, event)
  3282  	if isNull || err != nil {
  3283  		return "", "", isNull, err
  3284  	}
  3285  	if d < 0 {
  3286  		d = 0
  3287  	} else if d > formatMaxDecimals {
  3288  		d = formatMaxDecimals
  3289  	}
  3290  	xStr = roundFormatArgs(xStr, int(d))
  3291  	dStr := strconv.FormatInt(d, 10)
  3292  	return xStr, dStr, false, nil
  3293  }
  3294  
  3295  func roundFormatArgs(xStr string, maxNumDecimals int) string {
  3296  	if !strings.Contains(xStr, ".") {
  3297  		return xStr
  3298  	}
  3299  
  3300  	sign := false
  3301  	// xStr cannot have '+' prefix now.
  3302  	// It is built in `evalNumDecArgsFormat` after evaluating `Evalxxx` method.
  3303  	if strings.HasPrefix(xStr, "-") {
  3304  		xStr = strings.Trim(xStr, "-")
  3305  		sign = true
  3306  	}
  3307  
  3308  	xArr := strings.Split(xStr, ".")
  3309  	integerPart := xArr[0]
  3310  	decimalPart := xArr[1]
  3311  
  3312  	if len(decimalPart) > maxNumDecimals {
  3313  		t := []byte(decimalPart)
  3314  		carry := false
  3315  		if t[maxNumDecimals] >= '5' {
  3316  			carry = true
  3317  		}
  3318  		for i := maxNumDecimals - 1; i >= 0 && carry; i-- {
  3319  			if t[i] == '9' {
  3320  				t[i] = '0'
  3321  			} else {
  3322  				t[i] = t[i] + 1
  3323  				carry = false
  3324  			}
  3325  		}
  3326  		decimalPart = string(t)
  3327  		t = []byte(integerPart)
  3328  		for i := len(integerPart) - 1; i >= 0 && carry; i-- {
  3329  			if t[i] == '9' {
  3330  				t[i] = '0'
  3331  			} else {
  3332  				t[i] = t[i] + 1
  3333  				carry = false
  3334  			}
  3335  		}
  3336  		if carry {
  3337  			integerPart = "1" + string(t)
  3338  		} else {
  3339  			integerPart = string(t)
  3340  		}
  3341  	}
  3342  
  3343  	xStr = integerPart + "." + decimalPart
  3344  	if sign {
  3345  		xStr = "-" + xStr
  3346  	}
  3347  	return xStr
  3348  }
  3349  
  3350  type builtinFormatWithLocaleSig struct {
  3351  	baseBuiltinFunc
  3352  }
  3353  
  3354  func (b *builtinFormatWithLocaleSig) Clone() builtinFunc {
  3355  	newSig := &builtinFormatWithLocaleSig{}
  3356  	newSig.cloneFrom(&b.baseBuiltinFunc)
  3357  	return newSig
  3358  }
  3359  
  3360  // evalString evals FORMAT(X,D,locale).
  3361  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_format
  3362  func (b *builtinFormatWithLocaleSig) evalString(event chunk.Event) (string, bool, error) {
  3363  	x, d, isNull, err := evalNumDecArgsForFormat(b, event)
  3364  	if isNull || err != nil {
  3365  		return "", isNull, err
  3366  	}
  3367  	locale, isNull, err := b.args[2].EvalString(b.ctx, event)
  3368  	if err != nil {
  3369  		return "", false, err
  3370  	}
  3371  	if isNull {
  3372  		b.ctx.GetStochastikVars().StmtCtx.AppendWarning(errUnknownLocale.GenWithStackByArgs("NULL"))
  3373  		locale = "en_US"
  3374  	}
  3375  	formatString, err := allegrosql.GetLocaleFormatFunction(locale)(x, d)
  3376  	return formatString, false, err
  3377  }
  3378  
  3379  type builtinFormatSig struct {
  3380  	baseBuiltinFunc
  3381  }
  3382  
  3383  func (b *builtinFormatSig) Clone() builtinFunc {
  3384  	newSig := &builtinFormatSig{}
  3385  	newSig.cloneFrom(&b.baseBuiltinFunc)
  3386  	return newSig
  3387  }
  3388  
  3389  // evalString evals FORMAT(X,D).
  3390  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_format
  3391  func (b *builtinFormatSig) evalString(event chunk.Event) (string, bool, error) {
  3392  	x, d, isNull, err := evalNumDecArgsForFormat(b, event)
  3393  	if isNull || err != nil {
  3394  		return "", isNull, err
  3395  	}
  3396  	formatString, err := allegrosql.GetLocaleFormatFunction("en_US")(x, d)
  3397  	return formatString, false, err
  3398  }
  3399  
  3400  type fromBase64FunctionClass struct {
  3401  	baseFunctionClass
  3402  }
  3403  
  3404  func (c *fromBase64FunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  3405  	if err := c.verifyArgs(args); err != nil {
  3406  		return nil, err
  3407  	}
  3408  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString)
  3409  	if err != nil {
  3410  		return nil, err
  3411  	}
  3412  	bf.tp.Flen = allegrosql.MaxBlobWidth
  3413  
  3414  	valStr, _ := ctx.GetStochastikVars().GetSystemVar(variable.MaxAllowedPacket)
  3415  	maxAllowedPacket, err := strconv.ParseUint(valStr, 10, 64)
  3416  	if err != nil {
  3417  		return nil, errors.Trace(err)
  3418  	}
  3419  
  3420  	types.SetBinChsClnFlag(bf.tp)
  3421  	sig := &builtinFromBase64Sig{bf, maxAllowedPacket}
  3422  	return sig, nil
  3423  }
  3424  
  3425  // base64NeededDecodedLength return the base64 decoded string length.
  3426  func base64NeededDecodedLength(n int) int {
  3427  	// Returns -1 indicate the result will overflow.
  3428  	if strconv.IntSize == 64 && n > math.MaxInt64/3 {
  3429  		return -1
  3430  	}
  3431  	if strconv.IntSize == 32 && n > math.MaxInt32/3 {
  3432  		return -1
  3433  	}
  3434  	return n * 3 / 4
  3435  }
  3436  
  3437  type builtinFromBase64Sig struct {
  3438  	baseBuiltinFunc
  3439  	maxAllowedPacket uint64
  3440  }
  3441  
  3442  func (b *builtinFromBase64Sig) Clone() builtinFunc {
  3443  	newSig := &builtinFromBase64Sig{}
  3444  	newSig.cloneFrom(&b.baseBuiltinFunc)
  3445  	newSig.maxAllowedPacket = b.maxAllowedPacket
  3446  	return newSig
  3447  }
  3448  
  3449  // evalString evals FROM_BASE64(str).
  3450  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_from-base64
  3451  func (b *builtinFromBase64Sig) evalString(event chunk.Event) (string, bool, error) {
  3452  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
  3453  	if isNull || err != nil {
  3454  		return "", true, err
  3455  	}
  3456  
  3457  	needDecodeLen := base64NeededDecodedLength(len(str))
  3458  	if needDecodeLen == -1 {
  3459  		return "", true, nil
  3460  	}
  3461  	if needDecodeLen > int(b.maxAllowedPacket) {
  3462  		b.ctx.GetStochastikVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("from_base64", b.maxAllowedPacket))
  3463  		return "", true, nil
  3464  	}
  3465  
  3466  	str = strings.Replace(str, "\t", "", -1)
  3467  	str = strings.Replace(str, " ", "", -1)
  3468  	result, err := base64.StdEncoding.DecodeString(str)
  3469  	if err != nil {
  3470  		// When error happens, take `from_base64("asc")` as an example, we should return NULL.
  3471  		return "", true, nil
  3472  	}
  3473  	return string(result), false, nil
  3474  }
  3475  
  3476  type toBase64FunctionClass struct {
  3477  	baseFunctionClass
  3478  }
  3479  
  3480  func (c *toBase64FunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  3481  	if err := c.verifyArgs(args); err != nil {
  3482  		return nil, err
  3483  	}
  3484  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString)
  3485  	if err != nil {
  3486  		return nil, err
  3487  	}
  3488  	bf.tp.Charset, bf.tp.DefCauslate = ctx.GetStochastikVars().GetCharsetInfo()
  3489  	bf.tp.Flen = base64NeededEncodedLength(bf.args[0].GetType().Flen)
  3490  
  3491  	valStr, _ := ctx.GetStochastikVars().GetSystemVar(variable.MaxAllowedPacket)
  3492  	maxAllowedPacket, err := strconv.ParseUint(valStr, 10, 64)
  3493  	if err != nil {
  3494  		return nil, errors.Trace(err)
  3495  	}
  3496  
  3497  	sig := &builtinToBase64Sig{bf, maxAllowedPacket}
  3498  	return sig, nil
  3499  }
  3500  
  3501  type builtinToBase64Sig struct {
  3502  	baseBuiltinFunc
  3503  	maxAllowedPacket uint64
  3504  }
  3505  
  3506  func (b *builtinToBase64Sig) Clone() builtinFunc {
  3507  	newSig := &builtinToBase64Sig{}
  3508  	newSig.cloneFrom(&b.baseBuiltinFunc)
  3509  	newSig.maxAllowedPacket = b.maxAllowedPacket
  3510  	return newSig
  3511  }
  3512  
  3513  // base64NeededEncodedLength return the base64 encoded string length.
  3514  func base64NeededEncodedLength(n int) int {
  3515  	// Returns -1 indicate the result will overflow.
  3516  	if strconv.IntSize == 64 {
  3517  		// len(arg)            -> len(to_base64(arg))
  3518  		// 6827690988321067803 -> 9223372036854775804
  3519  		// 6827690988321067804 -> -9223372036854775808
  3520  		if n > 6827690988321067803 {
  3521  			return -1
  3522  		}
  3523  	} else {
  3524  		// len(arg)   -> len(to_base64(arg))
  3525  		// 1589695686 -> 2147483645
  3526  		// 1589695687 -> -2147483646
  3527  		if n > 1589695686 {
  3528  			return -1
  3529  		}
  3530  	}
  3531  
  3532  	length := (n + 2) / 3 * 4
  3533  	return length + (length-1)/76
  3534  }
  3535  
  3536  // evalString evals a builtinToBase64Sig.
  3537  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_to-base64
  3538  func (b *builtinToBase64Sig) evalString(event chunk.Event) (d string, isNull bool, err error) {
  3539  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
  3540  	if isNull || err != nil {
  3541  		return "", isNull, err
  3542  	}
  3543  	needEncodeLen := base64NeededEncodedLength(len(str))
  3544  	if needEncodeLen == -1 {
  3545  		return "", true, nil
  3546  	}
  3547  	if needEncodeLen > int(b.maxAllowedPacket) {
  3548  		b.ctx.GetStochastikVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("to_base64", b.maxAllowedPacket))
  3549  		return "", true, nil
  3550  	}
  3551  	if b.tp.Flen == -1 || b.tp.Flen > allegrosql.MaxBlobWidth {
  3552  		return "", true, nil
  3553  	}
  3554  
  3555  	//encode
  3556  	strBytes := []byte(str)
  3557  	result := base64.StdEncoding.EncodeToString(strBytes)
  3558  	//A newline is added after each 76 characters of encoded output to divide long output into multiple lines.
  3559  	count := len(result)
  3560  	if count > 76 {
  3561  		resultArr := splitToSubN(result, 76)
  3562  		result = strings.Join(resultArr, "\n")
  3563  	}
  3564  
  3565  	return result, false, nil
  3566  }
  3567  
  3568  // splitToSubN splits a string every n runes into a string[]
  3569  func splitToSubN(s string, n int) []string {
  3570  	subs := make([]string, 0, len(s)/n+1)
  3571  	for len(s) > n {
  3572  		subs = append(subs, s[:n])
  3573  		s = s[n:]
  3574  	}
  3575  	subs = append(subs, s)
  3576  	return subs
  3577  }
  3578  
  3579  type insertFunctionClass struct {
  3580  	baseFunctionClass
  3581  }
  3582  
  3583  func (c *insertFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) {
  3584  	if err = c.verifyArgs(args); err != nil {
  3585  		return nil, err
  3586  	}
  3587  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString, types.ETInt, types.ETInt, types.ETString)
  3588  	if err != nil {
  3589  		return nil, err
  3590  	}
  3591  	bf.tp.Flen = allegrosql.MaxBlobWidth
  3592  	SetBinFlagOrBinStr(args[0].GetType(), bf.tp)
  3593  	SetBinFlagOrBinStr(args[3].GetType(), bf.tp)
  3594  
  3595  	valStr, _ := ctx.GetStochastikVars().GetSystemVar(variable.MaxAllowedPacket)
  3596  	maxAllowedPacket, err := strconv.ParseUint(valStr, 10, 64)
  3597  	if err != nil {
  3598  		return nil, errors.Trace(err)
  3599  	}
  3600  
  3601  	if types.IsBinaryStr(args[0].GetType()) {
  3602  		sig = &builtinInsertSig{bf, maxAllowedPacket}
  3603  		sig.setPbCode(fidelpb.ScalarFuncSig_Insert)
  3604  	} else {
  3605  		sig = &builtinInsertUTF8Sig{bf, maxAllowedPacket}
  3606  		sig.setPbCode(fidelpb.ScalarFuncSig_InsertUTF8)
  3607  	}
  3608  	return sig, nil
  3609  }
  3610  
  3611  type builtinInsertSig struct {
  3612  	baseBuiltinFunc
  3613  	maxAllowedPacket uint64
  3614  }
  3615  
  3616  func (b *builtinInsertSig) Clone() builtinFunc {
  3617  	newSig := &builtinInsertSig{}
  3618  	newSig.cloneFrom(&b.baseBuiltinFunc)
  3619  	newSig.maxAllowedPacket = b.maxAllowedPacket
  3620  	return newSig
  3621  }
  3622  
  3623  // evalString evals INSERT(str,pos,len,newstr).
  3624  // See https://dev.allegrosql.com/doc/refman/5.6/en/string-functions.html#function_insert
  3625  func (b *builtinInsertSig) evalString(event chunk.Event) (string, bool, error) {
  3626  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
  3627  	if isNull || err != nil {
  3628  		return "", true, err
  3629  	}
  3630  
  3631  	pos, isNull, err := b.args[1].EvalInt(b.ctx, event)
  3632  	if isNull || err != nil {
  3633  		return "", true, err
  3634  	}
  3635  
  3636  	length, isNull, err := b.args[2].EvalInt(b.ctx, event)
  3637  	if isNull || err != nil {
  3638  		return "", true, err
  3639  	}
  3640  
  3641  	newstr, isNull, err := b.args[3].EvalString(b.ctx, event)
  3642  	if isNull || err != nil {
  3643  		return "", true, err
  3644  	}
  3645  
  3646  	strLength := int64(len(str))
  3647  	if pos < 1 || pos > strLength {
  3648  		return str, false, nil
  3649  	}
  3650  	if length > strLength-pos+1 || length < 0 {
  3651  		length = strLength - pos + 1
  3652  	}
  3653  
  3654  	if uint64(strLength-length+int64(len(newstr))) > b.maxAllowedPacket {
  3655  		b.ctx.GetStochastikVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("insert", b.maxAllowedPacket))
  3656  		return "", true, nil
  3657  	}
  3658  
  3659  	return str[0:pos-1] + newstr + str[pos+length-1:], false, nil
  3660  }
  3661  
  3662  type builtinInsertUTF8Sig struct {
  3663  	baseBuiltinFunc
  3664  	maxAllowedPacket uint64
  3665  }
  3666  
  3667  func (b *builtinInsertUTF8Sig) Clone() builtinFunc {
  3668  	newSig := &builtinInsertUTF8Sig{}
  3669  	newSig.cloneFrom(&b.baseBuiltinFunc)
  3670  	newSig.maxAllowedPacket = b.maxAllowedPacket
  3671  	return newSig
  3672  }
  3673  
  3674  // evalString evals INSERT(str,pos,len,newstr).
  3675  // See https://dev.allegrosql.com/doc/refman/5.6/en/string-functions.html#function_insert
  3676  func (b *builtinInsertUTF8Sig) evalString(event chunk.Event) (string, bool, error) {
  3677  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
  3678  	if isNull || err != nil {
  3679  		return "", true, err
  3680  	}
  3681  
  3682  	pos, isNull, err := b.args[1].EvalInt(b.ctx, event)
  3683  	if isNull || err != nil {
  3684  		return "", true, err
  3685  	}
  3686  
  3687  	length, isNull, err := b.args[2].EvalInt(b.ctx, event)
  3688  	if isNull || err != nil {
  3689  		return "", true, err
  3690  	}
  3691  
  3692  	newstr, isNull, err := b.args[3].EvalString(b.ctx, event)
  3693  	if isNull || err != nil {
  3694  		return "", true, err
  3695  	}
  3696  
  3697  	runes := []rune(str)
  3698  	runeLength := int64(len(runes))
  3699  	if pos < 1 || pos > runeLength {
  3700  		return str, false, nil
  3701  	}
  3702  	if length > runeLength-pos+1 || length < 0 {
  3703  		length = runeLength - pos + 1
  3704  	}
  3705  
  3706  	strHead := string(runes[0 : pos-1])
  3707  	strTail := string(runes[pos+length-1:])
  3708  	if uint64(len(strHead)+len(newstr)+len(strTail)) > b.maxAllowedPacket {
  3709  		b.ctx.GetStochastikVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("insert", b.maxAllowedPacket))
  3710  		return "", true, nil
  3711  	}
  3712  	return strHead + newstr + strTail, false, nil
  3713  }
  3714  
  3715  type instrFunctionClass struct {
  3716  	baseFunctionClass
  3717  }
  3718  
  3719  func (c *instrFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  3720  	if err := c.verifyArgs(args); err != nil {
  3721  		return nil, err
  3722  	}
  3723  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETString, types.ETString)
  3724  	if err != nil {
  3725  		return nil, err
  3726  	}
  3727  	bf.tp.Flen = 11
  3728  	if bf.defCauslation == charset.DefCauslationBin {
  3729  		sig := &builtinInstrSig{bf}
  3730  		sig.setPbCode(fidelpb.ScalarFuncSig_Instr)
  3731  		return sig, nil
  3732  	}
  3733  	sig := &builtinInstrUTF8Sig{bf}
  3734  	sig.setPbCode(fidelpb.ScalarFuncSig_InstrUTF8)
  3735  	return sig, nil
  3736  }
  3737  
  3738  type builtinInstrUTF8Sig struct{ baseBuiltinFunc }
  3739  
  3740  func (b *builtinInstrUTF8Sig) Clone() builtinFunc {
  3741  	newSig := &builtinInstrUTF8Sig{}
  3742  	newSig.cloneFrom(&b.baseBuiltinFunc)
  3743  	return newSig
  3744  }
  3745  
  3746  type builtinInstrSig struct{ baseBuiltinFunc }
  3747  
  3748  func (b *builtinInstrSig) Clone() builtinFunc {
  3749  	newSig := &builtinInstrSig{}
  3750  	newSig.cloneFrom(&b.baseBuiltinFunc)
  3751  	return newSig
  3752  }
  3753  
  3754  // evalInt evals INSTR(str,substr).
  3755  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_instr
  3756  func (b *builtinInstrUTF8Sig) evalInt(event chunk.Event) (int64, bool, error) {
  3757  	str, IsNull, err := b.args[0].EvalString(b.ctx, event)
  3758  	if IsNull || err != nil {
  3759  		return 0, true, err
  3760  	}
  3761  	substr, IsNull, err := b.args[1].EvalString(b.ctx, event)
  3762  	if IsNull || err != nil {
  3763  		return 0, true, err
  3764  	}
  3765  	if defCauslate.IsCIDefCauslation(b.defCauslation) {
  3766  		str = strings.ToLower(str)
  3767  		substr = strings.ToLower(substr)
  3768  	}
  3769  
  3770  	idx := strings.Index(str, substr)
  3771  	if idx == -1 {
  3772  		return 0, false, nil
  3773  	}
  3774  	return int64(utf8.RuneCountInString(str[:idx]) + 1), false, nil
  3775  }
  3776  
  3777  // evalInt evals INSTR(str,substr), case sensitive.
  3778  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_instr
  3779  func (b *builtinInstrSig) evalInt(event chunk.Event) (int64, bool, error) {
  3780  	str, IsNull, err := b.args[0].EvalString(b.ctx, event)
  3781  	if IsNull || err != nil {
  3782  		return 0, true, err
  3783  	}
  3784  
  3785  	substr, IsNull, err := b.args[1].EvalString(b.ctx, event)
  3786  	if IsNull || err != nil {
  3787  		return 0, true, err
  3788  	}
  3789  
  3790  	idx := strings.Index(str, substr)
  3791  	if idx == -1 {
  3792  		return 0, false, nil
  3793  	}
  3794  	return int64(idx + 1), false, nil
  3795  }
  3796  
  3797  type loadFileFunctionClass struct {
  3798  	baseFunctionClass
  3799  }
  3800  
  3801  func (c *loadFileFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  3802  	return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "load_file")
  3803  }
  3804  
  3805  type weightStringPadding byte
  3806  
  3807  const (
  3808  	// weightStringPaddingNone is used for WEIGHT_STRING(expr) if the expr is non-numeric.
  3809  	weightStringPaddingNone weightStringPadding = iota
  3810  	// weightStringPaddingAsChar is used for WEIGHT_STRING(expr AS CHAR(x)) and the expr is non-numeric.
  3811  	weightStringPaddingAsChar
  3812  	// weightStringPaddingAsBinary is used for WEIGHT_STRING(expr as BINARY(x)) and the expr is not null.
  3813  	weightStringPaddingAsBinary
  3814  	// weightStringPaddingNull is used for WEIGHT_STRING(expr [AS (CHAR|BINARY)]) for all other cases, it returns null always.
  3815  	weightStringPaddingNull
  3816  )
  3817  
  3818  type weightStringFunctionClass struct {
  3819  	baseFunctionClass
  3820  }
  3821  
  3822  func (c *weightStringFunctionClass) verifyArgs(args []Expression) (weightStringPadding, int, error) {
  3823  	padding := weightStringPaddingNone
  3824  	l := len(args)
  3825  	if l != 1 && l != 3 {
  3826  		return weightStringPaddingNone, 0, ErrIncorrectParameterCount.GenWithStackByArgs(c.funcName)
  3827  	}
  3828  	if types.IsTypeNumeric(args[0].GetType().Tp) {
  3829  		padding = weightStringPaddingNull
  3830  	}
  3831  	length := 0
  3832  	if l == 3 {
  3833  		if args[1].GetType().EvalType() != types.ETString {
  3834  			return weightStringPaddingNone, 0, ErrIncorrectType.GenWithStackByArgs(args[1].String(), c.funcName)
  3835  		}
  3836  		c1, ok := args[1].(*Constant)
  3837  		if !ok {
  3838  			return weightStringPaddingNone, 0, ErrIncorrectType.GenWithStackByArgs(args[1].String(), c.funcName)
  3839  		}
  3840  		switch x := c1.Value.GetString(); x {
  3841  		case "CHAR":
  3842  			if padding == weightStringPaddingNone {
  3843  				padding = weightStringPaddingAsChar
  3844  			}
  3845  		case "BINARY":
  3846  			padding = weightStringPaddingAsBinary
  3847  		default:
  3848  			return weightStringPaddingNone, 0, ErrIncorrectType.GenWithStackByArgs(x, c.funcName)
  3849  		}
  3850  		if args[2].GetType().EvalType() != types.ETInt {
  3851  			return weightStringPaddingNone, 0, ErrIncorrectType.GenWithStackByArgs(args[2].String(), c.funcName)
  3852  		}
  3853  		c2, ok := args[2].(*Constant)
  3854  		if !ok {
  3855  			return weightStringPaddingNone, 0, ErrIncorrectType.GenWithStackByArgs(args[1].String(), c.funcName)
  3856  		}
  3857  		length = int(c2.Value.GetInt64())
  3858  		if length == 0 {
  3859  			return weightStringPaddingNone, 0, ErrIncorrectType.GenWithStackByArgs(args[2].String(), c.funcName)
  3860  		}
  3861  	}
  3862  	return padding, length, nil
  3863  }
  3864  
  3865  func (c *weightStringFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  3866  	padding, length, err := c.verifyArgs(args)
  3867  	if err != nil {
  3868  		return nil, err
  3869  	}
  3870  	argTps := make([]types.EvalType, len(args))
  3871  	argTps[0] = types.ETString
  3872  
  3873  	if len(args) == 3 {
  3874  		argTps[1] = types.ETString
  3875  		argTps[2] = types.ETInt
  3876  	}
  3877  
  3878  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, argTps...)
  3879  	if err != nil {
  3880  		return nil, err
  3881  	}
  3882  	var sig builtinFunc
  3883  	if padding == weightStringPaddingNull {
  3884  		sig = &builtinWeightStringNullSig{bf}
  3885  	} else {
  3886  		sig = &builtinWeightStringSig{bf, padding, length}
  3887  	}
  3888  	return sig, nil
  3889  }
  3890  
  3891  type builtinWeightStringNullSig struct {
  3892  	baseBuiltinFunc
  3893  }
  3894  
  3895  func (b *builtinWeightStringNullSig) Clone() builtinFunc {
  3896  	newSig := &builtinWeightStringNullSig{}
  3897  	newSig.cloneFrom(&b.baseBuiltinFunc)
  3898  	return newSig
  3899  }
  3900  
  3901  // evalString evals a WEIGHT_STRING(expr [AS CHAR|BINARY]) when the expr is numeric types, it always returns null.
  3902  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_weight-string
  3903  func (b *builtinWeightStringNullSig) evalString(event chunk.Event) (string, bool, error) {
  3904  	return "", true, nil
  3905  }
  3906  
  3907  type builtinWeightStringSig struct {
  3908  	baseBuiltinFunc
  3909  
  3910  	padding weightStringPadding
  3911  	length  int
  3912  }
  3913  
  3914  func (b *builtinWeightStringSig) Clone() builtinFunc {
  3915  	newSig := &builtinWeightStringSig{}
  3916  	newSig.cloneFrom(&b.baseBuiltinFunc)
  3917  	newSig.padding = b.padding
  3918  	newSig.length = b.length
  3919  	return newSig
  3920  }
  3921  
  3922  // evalString evals a WEIGHT_STRING(expr [AS (CHAR|BINARY)]) when the expr is non-numeric types.
  3923  // See https://dev.allegrosql.com/doc/refman/5.7/en/string-functions.html#function_weight-string
  3924  func (b *builtinWeightStringSig) evalString(event chunk.Event) (string, bool, error) {
  3925  	str, isNull, err := b.args[0].EvalString(b.ctx, event)
  3926  	if err != nil {
  3927  		return "", false, err
  3928  	}
  3929  	if isNull {
  3930  		return "", true, nil
  3931  	}
  3932  
  3933  	var ctor defCauslate.DefCauslator
  3934  	// TODO: refactor padding codes after padding is implemented by all defCauslators.
  3935  	switch b.padding {
  3936  	case weightStringPaddingAsChar:
  3937  		runes := []rune(str)
  3938  		lenRunes := len(runes)
  3939  		if b.length < lenRunes {
  3940  			str = string(runes[:b.length])
  3941  		} else if b.length > lenRunes {
  3942  			str += strings.Repeat(" ", b.length-lenRunes)
  3943  		}
  3944  		ctor = defCauslate.GetDefCauslator(b.args[0].GetType().DefCauslate)
  3945  	case weightStringPaddingAsBinary:
  3946  		lenStr := len(str)
  3947  		if b.length < lenStr {
  3948  			tpInfo := fmt.Sprintf("BINARY(%d)", b.length)
  3949  			b.ctx.GetStochastikVars().StmtCtx.AppendWarning(errTruncatedWrongValue.GenWithStackByArgs(tpInfo, str))
  3950  			str = str[:b.length]
  3951  		} else if b.length > lenStr {
  3952  			str += strings.Repeat("\x00", b.length-lenStr)
  3953  		}
  3954  		ctor = defCauslate.GetDefCauslator(charset.DefCauslationBin)
  3955  	case weightStringPaddingNone:
  3956  		ctor = defCauslate.GetDefCauslator(b.args[0].GetType().DefCauslate)
  3957  	default:
  3958  		return "", false, ErrIncorrectType.GenWithStackByArgs(ast.WeightString, string(b.padding))
  3959  	}
  3960  	return string(ctor.Key(str)), false, nil
  3961  }