github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/memex/builtin_other.go (about)

     1  // Copyright 2020 WHTCORPS INC, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package memex
    15  
    16  import (
    17  	"strings"
    18  	"time"
    19  
    20  	"github.com/whtcorpsinc/errors"
    21  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    22  	"github.com/whtcorpsinc/milevadb/stochastikctx"
    23  	"github.com/whtcorpsinc/milevadb/types"
    24  	"github.com/whtcorpsinc/milevadb/types/json"
    25  	"github.com/whtcorpsinc/milevadb/soliton/chunk"
    26  	"github.com/whtcorpsinc/milevadb/soliton/defCauslate"
    27  	"github.com/whtcorpsinc/milevadb/soliton/set"
    28  	"github.com/whtcorpsinc/milevadb/soliton/stringutil"
    29  	"github.com/whtcorpsinc/fidelpb/go-fidelpb"
    30  )
    31  
    32  var (
    33  	_ functionClass = &inFunctionClass{}
    34  	_ functionClass = &rowFunctionClass{}
    35  	_ functionClass = &setVarFunctionClass{}
    36  	_ functionClass = &getVarFunctionClass{}
    37  	_ functionClass = &lockFunctionClass{}
    38  	_ functionClass = &releaseLockFunctionClass{}
    39  	_ functionClass = &valuesFunctionClass{}
    40  	_ functionClass = &bitCountFunctionClass{}
    41  	_ functionClass = &getParamFunctionClass{}
    42  )
    43  
    44  var (
    45  	_ builtinFunc = &builtinSleepSig{}
    46  	_ builtinFunc = &builtinInIntSig{}
    47  	_ builtinFunc = &builtinInStringSig{}
    48  	_ builtinFunc = &builtinInDecimalSig{}
    49  	_ builtinFunc = &builtinInRealSig{}
    50  	_ builtinFunc = &builtinInTimeSig{}
    51  	_ builtinFunc = &builtinInDurationSig{}
    52  	_ builtinFunc = &builtinInJSONSig{}
    53  	_ builtinFunc = &builtinEventSig{}
    54  	_ builtinFunc = &builtinSetVarSig{}
    55  	_ builtinFunc = &builtinGetVarSig{}
    56  	_ builtinFunc = &builtinLockSig{}
    57  	_ builtinFunc = &builtinReleaseLockSig{}
    58  	_ builtinFunc = &builtinValuesIntSig{}
    59  	_ builtinFunc = &builtinValuesRealSig{}
    60  	_ builtinFunc = &builtinValuesDecimalSig{}
    61  	_ builtinFunc = &builtinValuesStringSig{}
    62  	_ builtinFunc = &builtinValuesTimeSig{}
    63  	_ builtinFunc = &builtinValuesDurationSig{}
    64  	_ builtinFunc = &builtinValuesJSONSig{}
    65  	_ builtinFunc = &builtinBitCountSig{}
    66  	_ builtinFunc = &builtinGetParamStringSig{}
    67  )
    68  
    69  type inFunctionClass struct {
    70  	baseFunctionClass
    71  }
    72  
    73  func (c *inFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) {
    74  	if err := c.verifyArgs(args); err != nil {
    75  		return nil, err
    76  	}
    77  	argTps := make([]types.EvalType, len(args))
    78  	for i := range args {
    79  		argTps[i] = args[0].GetType().EvalType()
    80  	}
    81  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, argTps...)
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  	bf.tp.Flen = 1
    86  	switch args[0].GetType().EvalType() {
    87  	case types.ETInt:
    88  		inInt := builtinInIntSig{baseInSig: baseInSig{baseBuiltinFunc: bf}}
    89  		err := inInt.buildHashMapForConstArgs(ctx)
    90  		if err != nil {
    91  			return &inInt, err
    92  		}
    93  		sig = &inInt
    94  		sig.setPbCode(fidelpb.ScalarFuncSig_InInt)
    95  	case types.ETString:
    96  		inStr := builtinInStringSig{baseInSig: baseInSig{baseBuiltinFunc: bf}}
    97  		err := inStr.buildHashMapForConstArgs(ctx)
    98  		if err != nil {
    99  			return &inStr, err
   100  		}
   101  		sig = &inStr
   102  		sig.setPbCode(fidelpb.ScalarFuncSig_InString)
   103  	case types.ETReal:
   104  		inReal := builtinInRealSig{baseInSig: baseInSig{baseBuiltinFunc: bf}}
   105  		err := inReal.buildHashMapForConstArgs(ctx)
   106  		if err != nil {
   107  			return &inReal, err
   108  		}
   109  		sig = &inReal
   110  		sig.setPbCode(fidelpb.ScalarFuncSig_InReal)
   111  	case types.ETDecimal:
   112  		inDecimal := builtinInDecimalSig{baseInSig: baseInSig{baseBuiltinFunc: bf}}
   113  		err := inDecimal.buildHashMapForConstArgs(ctx)
   114  		if err != nil {
   115  			return &inDecimal, err
   116  		}
   117  		sig = &inDecimal
   118  		sig.setPbCode(fidelpb.ScalarFuncSig_InDecimal)
   119  	case types.ETDatetime, types.ETTimestamp:
   120  		inTime := builtinInTimeSig{baseInSig: baseInSig{baseBuiltinFunc: bf}}
   121  		err := inTime.buildHashMapForConstArgs(ctx)
   122  		if err != nil {
   123  			return &inTime, err
   124  		}
   125  		sig = &inTime
   126  		sig.setPbCode(fidelpb.ScalarFuncSig_InTime)
   127  	case types.ETDuration:
   128  		inDuration := builtinInDurationSig{baseInSig: baseInSig{baseBuiltinFunc: bf}}
   129  		err := inDuration.buildHashMapForConstArgs(ctx)
   130  		if err != nil {
   131  			return &inDuration, err
   132  		}
   133  		sig = &inDuration
   134  		sig.setPbCode(fidelpb.ScalarFuncSig_InDuration)
   135  	case types.ETJson:
   136  		sig = &builtinInJSONSig{baseBuiltinFunc: bf}
   137  		sig.setPbCode(fidelpb.ScalarFuncSig_InJson)
   138  	}
   139  	return sig, nil
   140  }
   141  
   142  type baseInSig struct {
   143  	baseBuiltinFunc
   144  	nonConstArgs []Expression
   145  	hasNull      bool
   146  }
   147  
   148  // builtinInIntSig see https://dev.allegrosql.com/doc/refman/5.7/en/comparison-operators.html#function_in
   149  type builtinInIntSig struct {
   150  	baseInSig
   151  	// the bool value in the map is used to identify whether the constant stored in key is signed or unsigned
   152  	hashSet map[int64]bool
   153  }
   154  
   155  func (b *builtinInIntSig) buildHashMapForConstArgs(ctx stochastikctx.Context) error {
   156  	b.nonConstArgs = []Expression{b.args[0]}
   157  	b.hashSet = make(map[int64]bool, len(b.args)-1)
   158  	for i := 1; i < len(b.args); i++ {
   159  		if b.args[i].ConstItem(b.ctx.GetStochastikVars().StmtCtx) {
   160  			val, isNull, err := b.args[i].EvalInt(ctx, chunk.Event{})
   161  			if err != nil {
   162  				return err
   163  			}
   164  			if isNull {
   165  				b.hasNull = true
   166  				continue
   167  			}
   168  			b.hashSet[val] = allegrosql.HasUnsignedFlag(b.args[i].GetType().Flag)
   169  		} else {
   170  			b.nonConstArgs = append(b.nonConstArgs, b.args[i])
   171  		}
   172  	}
   173  	return nil
   174  }
   175  
   176  func (b *builtinInIntSig) Clone() builtinFunc {
   177  	newSig := &builtinInIntSig{}
   178  	newSig.cloneFrom(&b.baseBuiltinFunc)
   179  	newSig.nonConstArgs = make([]Expression, 0, len(b.nonConstArgs))
   180  	for _, arg := range b.nonConstArgs {
   181  		newSig.nonConstArgs = append(newSig.nonConstArgs, arg.Clone())
   182  	}
   183  	newSig.hashSet = b.hashSet
   184  	newSig.hasNull = b.hasNull
   185  	return newSig
   186  }
   187  
   188  func (b *builtinInIntSig) evalInt(event chunk.Event) (int64, bool, error) {
   189  	arg0, isNull0, err := b.args[0].EvalInt(b.ctx, event)
   190  	if isNull0 || err != nil {
   191  		return 0, isNull0, err
   192  	}
   193  	isUnsigned0 := allegrosql.HasUnsignedFlag(b.args[0].GetType().Flag)
   194  
   195  	args := b.args
   196  	if len(b.hashSet) != 0 {
   197  		args = b.nonConstArgs
   198  		if isUnsigned, ok := b.hashSet[arg0]; ok {
   199  			if (isUnsigned0 && isUnsigned) || (!isUnsigned0 && !isUnsigned) {
   200  				return 1, false, nil
   201  			}
   202  			if arg0 >= 0 {
   203  				return 1, false, nil
   204  			}
   205  		}
   206  	}
   207  
   208  	hasNull := b.hasNull
   209  	for _, arg := range args[1:] {
   210  		evaledArg, isNull, err := arg.EvalInt(b.ctx, event)
   211  		if err != nil {
   212  			return 0, true, err
   213  		}
   214  		if isNull {
   215  			hasNull = true
   216  			continue
   217  		}
   218  		isUnsigned := allegrosql.HasUnsignedFlag(arg.GetType().Flag)
   219  		if isUnsigned0 && isUnsigned {
   220  			if evaledArg == arg0 {
   221  				return 1, false, nil
   222  			}
   223  		} else if !isUnsigned0 && !isUnsigned {
   224  			if evaledArg == arg0 {
   225  				return 1, false, nil
   226  			}
   227  		} else if !isUnsigned0 && isUnsigned {
   228  			if arg0 >= 0 && evaledArg == arg0 {
   229  				return 1, false, nil
   230  			}
   231  		} else {
   232  			if evaledArg >= 0 && evaledArg == arg0 {
   233  				return 1, false, nil
   234  			}
   235  		}
   236  	}
   237  	return 0, hasNull, nil
   238  }
   239  
   240  // builtinInStringSig see https://dev.allegrosql.com/doc/refman/5.7/en/comparison-operators.html#function_in
   241  type builtinInStringSig struct {
   242  	baseInSig
   243  	hashSet set.StringSet
   244  }
   245  
   246  func (b *builtinInStringSig) buildHashMapForConstArgs(ctx stochastikctx.Context) error {
   247  	b.nonConstArgs = []Expression{b.args[0]}
   248  	b.hashSet = set.NewStringSet()
   249  	defCauslator := defCauslate.GetDefCauslator(b.defCauslation)
   250  	for i := 1; i < len(b.args); i++ {
   251  		if b.args[i].ConstItem(b.ctx.GetStochastikVars().StmtCtx) {
   252  			val, isNull, err := b.args[i].EvalString(ctx, chunk.Event{})
   253  			if err != nil {
   254  				return err
   255  			}
   256  			if isNull {
   257  				b.hasNull = true
   258  				continue
   259  			}
   260  			b.hashSet.Insert(string(defCauslator.Key(val))) // should do memory copy here
   261  		} else {
   262  			b.nonConstArgs = append(b.nonConstArgs, b.args[i])
   263  		}
   264  	}
   265  
   266  	return nil
   267  }
   268  
   269  func (b *builtinInStringSig) Clone() builtinFunc {
   270  	newSig := &builtinInStringSig{}
   271  	newSig.cloneFrom(&b.baseBuiltinFunc)
   272  	newSig.nonConstArgs = make([]Expression, 0, len(b.nonConstArgs))
   273  	for _, arg := range b.nonConstArgs {
   274  		newSig.nonConstArgs = append(newSig.nonConstArgs, arg.Clone())
   275  	}
   276  	newSig.hashSet = b.hashSet
   277  	newSig.hasNull = b.hasNull
   278  	return newSig
   279  }
   280  
   281  func (b *builtinInStringSig) evalInt(event chunk.Event) (int64, bool, error) {
   282  	arg0, isNull0, err := b.args[0].EvalString(b.ctx, event)
   283  	if isNull0 || err != nil {
   284  		return 0, isNull0, err
   285  	}
   286  
   287  	args := b.args
   288  	defCauslator := defCauslate.GetDefCauslator(b.defCauslation)
   289  	if len(b.hashSet) != 0 {
   290  		args = b.nonConstArgs
   291  		if b.hashSet.Exist(string(defCauslator.Key(arg0))) {
   292  			return 1, false, nil
   293  		}
   294  	}
   295  
   296  	hasNull := b.hasNull
   297  	for _, arg := range args[1:] {
   298  		evaledArg, isNull, err := arg.EvalString(b.ctx, event)
   299  		if err != nil {
   300  			return 0, true, err
   301  		}
   302  		if isNull {
   303  			hasNull = true
   304  			continue
   305  		}
   306  		if types.CompareString(arg0, evaledArg, b.defCauslation) == 0 {
   307  			return 1, false, nil
   308  		}
   309  	}
   310  	return 0, hasNull, nil
   311  }
   312  
   313  // builtinInRealSig see https://dev.allegrosql.com/doc/refman/5.7/en/comparison-operators.html#function_in
   314  type builtinInRealSig struct {
   315  	baseInSig
   316  	hashSet set.Float64Set
   317  }
   318  
   319  func (b *builtinInRealSig) buildHashMapForConstArgs(ctx stochastikctx.Context) error {
   320  	b.nonConstArgs = []Expression{b.args[0]}
   321  	b.hashSet = set.NewFloat64Set()
   322  	for i := 1; i < len(b.args); i++ {
   323  		if b.args[i].ConstItem(b.ctx.GetStochastikVars().StmtCtx) {
   324  			val, isNull, err := b.args[i].EvalReal(ctx, chunk.Event{})
   325  			if err != nil {
   326  				return err
   327  			}
   328  			if isNull {
   329  				b.hasNull = true
   330  				continue
   331  			}
   332  			b.hashSet.Insert(val)
   333  		} else {
   334  			b.nonConstArgs = append(b.nonConstArgs, b.args[i])
   335  		}
   336  	}
   337  
   338  	return nil
   339  }
   340  
   341  func (b *builtinInRealSig) Clone() builtinFunc {
   342  	newSig := &builtinInRealSig{}
   343  	newSig.cloneFrom(&b.baseBuiltinFunc)
   344  	newSig.nonConstArgs = make([]Expression, 0, len(b.nonConstArgs))
   345  	for _, arg := range b.nonConstArgs {
   346  		newSig.nonConstArgs = append(newSig.nonConstArgs, arg.Clone())
   347  	}
   348  	newSig.hashSet = b.hashSet
   349  	newSig.hasNull = b.hasNull
   350  	return newSig
   351  }
   352  
   353  func (b *builtinInRealSig) evalInt(event chunk.Event) (int64, bool, error) {
   354  	arg0, isNull0, err := b.args[0].EvalReal(b.ctx, event)
   355  	if isNull0 || err != nil {
   356  		return 0, isNull0, err
   357  	}
   358  	args := b.args
   359  	if len(b.hashSet) != 0 {
   360  		args = b.nonConstArgs
   361  		if b.hashSet.Exist(arg0) {
   362  			return 1, false, nil
   363  		}
   364  	}
   365  	hasNull := b.hasNull
   366  	for _, arg := range args[1:] {
   367  		evaledArg, isNull, err := arg.EvalReal(b.ctx, event)
   368  		if err != nil {
   369  			return 0, true, err
   370  		}
   371  		if isNull {
   372  			hasNull = true
   373  			continue
   374  		}
   375  		if arg0 == evaledArg {
   376  			return 1, false, nil
   377  		}
   378  	}
   379  	return 0, hasNull, nil
   380  }
   381  
   382  // builtinInDecimalSig see https://dev.allegrosql.com/doc/refman/5.7/en/comparison-operators.html#function_in
   383  type builtinInDecimalSig struct {
   384  	baseInSig
   385  	hashSet set.StringSet
   386  }
   387  
   388  func (b *builtinInDecimalSig) buildHashMapForConstArgs(ctx stochastikctx.Context) error {
   389  	b.nonConstArgs = []Expression{b.args[0]}
   390  	b.hashSet = set.NewStringSet()
   391  	for i := 1; i < len(b.args); i++ {
   392  		if b.args[i].ConstItem(b.ctx.GetStochastikVars().StmtCtx) {
   393  			val, isNull, err := b.args[i].EvalDecimal(ctx, chunk.Event{})
   394  			if err != nil {
   395  				return err
   396  			}
   397  			if isNull {
   398  				b.hasNull = true
   399  				continue
   400  			}
   401  			key, err := val.ToHashKey()
   402  			if err != nil {
   403  				return err
   404  			}
   405  			b.hashSet.Insert(string(key))
   406  		} else {
   407  			b.nonConstArgs = append(b.nonConstArgs, b.args[i])
   408  		}
   409  	}
   410  
   411  	return nil
   412  }
   413  
   414  func (b *builtinInDecimalSig) Clone() builtinFunc {
   415  	newSig := &builtinInDecimalSig{}
   416  	newSig.cloneFrom(&b.baseBuiltinFunc)
   417  	newSig.nonConstArgs = make([]Expression, 0, len(b.nonConstArgs))
   418  	for _, arg := range b.nonConstArgs {
   419  		newSig.nonConstArgs = append(newSig.nonConstArgs, arg.Clone())
   420  	}
   421  	newSig.hashSet = b.hashSet
   422  	newSig.hasNull = b.hasNull
   423  	return newSig
   424  }
   425  
   426  func (b *builtinInDecimalSig) evalInt(event chunk.Event) (int64, bool, error) {
   427  	arg0, isNull0, err := b.args[0].EvalDecimal(b.ctx, event)
   428  	if isNull0 || err != nil {
   429  		return 0, isNull0, err
   430  	}
   431  
   432  	args := b.args
   433  	key, err := arg0.ToHashKey()
   434  	if err != nil {
   435  		return 0, true, err
   436  	}
   437  	if len(b.hashSet) != 0 {
   438  		args = b.nonConstArgs
   439  		if b.hashSet.Exist(string(key)) {
   440  			return 1, false, nil
   441  		}
   442  	}
   443  
   444  	hasNull := b.hasNull
   445  	for _, arg := range args[1:] {
   446  		evaledArg, isNull, err := arg.EvalDecimal(b.ctx, event)
   447  		if err != nil {
   448  			return 0, true, err
   449  		}
   450  		if isNull {
   451  			hasNull = true
   452  			continue
   453  		}
   454  		if arg0.Compare(evaledArg) == 0 {
   455  			return 1, false, nil
   456  		}
   457  	}
   458  	return 0, hasNull, nil
   459  }
   460  
   461  // builtinInTimeSig see https://dev.allegrosql.com/doc/refman/5.7/en/comparison-operators.html#function_in
   462  type builtinInTimeSig struct {
   463  	baseInSig
   464  	hashSet map[types.Time]struct{}
   465  }
   466  
   467  func (b *builtinInTimeSig) buildHashMapForConstArgs(ctx stochastikctx.Context) error {
   468  	b.nonConstArgs = []Expression{b.args[0]}
   469  	b.hashSet = make(map[types.Time]struct{}, len(b.args)-1)
   470  	for i := 1; i < len(b.args); i++ {
   471  		if b.args[i].ConstItem(b.ctx.GetStochastikVars().StmtCtx) {
   472  			val, isNull, err := b.args[i].EvalTime(ctx, chunk.Event{})
   473  			if err != nil {
   474  				return err
   475  			}
   476  			if isNull {
   477  				b.hasNull = true
   478  				continue
   479  			}
   480  			b.hashSet[val] = struct{}{}
   481  		} else {
   482  			b.nonConstArgs = append(b.nonConstArgs, b.args[i])
   483  		}
   484  	}
   485  
   486  	return nil
   487  }
   488  
   489  func (b *builtinInTimeSig) Clone() builtinFunc {
   490  	newSig := &builtinInTimeSig{}
   491  	newSig.cloneFrom(&b.baseBuiltinFunc)
   492  	newSig.nonConstArgs = make([]Expression, 0, len(b.nonConstArgs))
   493  	for _, arg := range b.nonConstArgs {
   494  		newSig.nonConstArgs = append(newSig.nonConstArgs, arg.Clone())
   495  	}
   496  	newSig.hashSet = b.hashSet
   497  	newSig.hasNull = b.hasNull
   498  	return newSig
   499  }
   500  
   501  func (b *builtinInTimeSig) evalInt(event chunk.Event) (int64, bool, error) {
   502  	arg0, isNull0, err := b.args[0].EvalTime(b.ctx, event)
   503  	if isNull0 || err != nil {
   504  		return 0, isNull0, err
   505  	}
   506  	args := b.args
   507  	if len(b.hashSet) != 0 {
   508  		args = b.nonConstArgs
   509  		if _, ok := b.hashSet[arg0]; ok {
   510  			return 1, false, nil
   511  		}
   512  	}
   513  	hasNull := b.hasNull
   514  	for _, arg := range args[1:] {
   515  		evaledArg, isNull, err := arg.EvalTime(b.ctx, event)
   516  		if err != nil {
   517  			return 0, true, err
   518  		}
   519  		if isNull {
   520  			hasNull = true
   521  			continue
   522  		}
   523  		if arg0.Compare(evaledArg) == 0 {
   524  			return 1, false, nil
   525  		}
   526  	}
   527  	return 0, hasNull, nil
   528  }
   529  
   530  // builtinInDurationSig see https://dev.allegrosql.com/doc/refman/5.7/en/comparison-operators.html#function_in
   531  type builtinInDurationSig struct {
   532  	baseInSig
   533  	hashSet map[time.Duration]struct{}
   534  }
   535  
   536  func (b *builtinInDurationSig) buildHashMapForConstArgs(ctx stochastikctx.Context) error {
   537  	b.nonConstArgs = []Expression{b.args[0]}
   538  	b.hashSet = make(map[time.Duration]struct{}, len(b.args)-1)
   539  	for i := 1; i < len(b.args); i++ {
   540  		if b.args[i].ConstItem(b.ctx.GetStochastikVars().StmtCtx) {
   541  			val, isNull, err := b.args[i].EvalDuration(ctx, chunk.Event{})
   542  			if err != nil {
   543  				return err
   544  			}
   545  			if isNull {
   546  				b.hasNull = true
   547  				continue
   548  			}
   549  			b.hashSet[val.Duration] = struct{}{}
   550  		} else {
   551  			b.nonConstArgs = append(b.nonConstArgs, b.args[i])
   552  		}
   553  	}
   554  
   555  	return nil
   556  }
   557  
   558  func (b *builtinInDurationSig) Clone() builtinFunc {
   559  	newSig := &builtinInDurationSig{}
   560  	newSig.cloneFrom(&b.baseBuiltinFunc)
   561  	newSig.nonConstArgs = make([]Expression, 0, len(b.nonConstArgs))
   562  	for _, arg := range b.nonConstArgs {
   563  		newSig.nonConstArgs = append(newSig.nonConstArgs, arg.Clone())
   564  	}
   565  	newSig.hashSet = b.hashSet
   566  	newSig.hasNull = b.hasNull
   567  	return newSig
   568  }
   569  
   570  func (b *builtinInDurationSig) evalInt(event chunk.Event) (int64, bool, error) {
   571  	arg0, isNull0, err := b.args[0].EvalDuration(b.ctx, event)
   572  	if isNull0 || err != nil {
   573  		return 0, isNull0, err
   574  	}
   575  	args := b.args
   576  	if len(b.hashSet) != 0 {
   577  		args = b.nonConstArgs
   578  		if _, ok := b.hashSet[arg0.Duration]; ok {
   579  			return 1, false, nil
   580  		}
   581  	}
   582  	hasNull := b.hasNull
   583  	for _, arg := range args[1:] {
   584  		evaledArg, isNull, err := arg.EvalDuration(b.ctx, event)
   585  		if err != nil {
   586  			return 0, true, err
   587  		}
   588  		if isNull {
   589  			hasNull = true
   590  			continue
   591  		}
   592  		if arg0.Compare(evaledArg) == 0 {
   593  			return 1, false, nil
   594  		}
   595  	}
   596  	return 0, hasNull, nil
   597  }
   598  
   599  // builtinInJSONSig see https://dev.allegrosql.com/doc/refman/5.7/en/comparison-operators.html#function_in
   600  type builtinInJSONSig struct {
   601  	baseBuiltinFunc
   602  }
   603  
   604  func (b *builtinInJSONSig) Clone() builtinFunc {
   605  	newSig := &builtinInJSONSig{}
   606  	newSig.cloneFrom(&b.baseBuiltinFunc)
   607  	return newSig
   608  }
   609  
   610  func (b *builtinInJSONSig) evalInt(event chunk.Event) (int64, bool, error) {
   611  	arg0, isNull0, err := b.args[0].EvalJSON(b.ctx, event)
   612  	if isNull0 || err != nil {
   613  		return 0, isNull0, err
   614  	}
   615  	var hasNull bool
   616  	for _, arg := range b.args[1:] {
   617  		evaledArg, isNull, err := arg.EvalJSON(b.ctx, event)
   618  		if err != nil {
   619  			return 0, true, err
   620  		}
   621  		if isNull {
   622  			hasNull = true
   623  			continue
   624  		}
   625  		result := json.CompareBinary(evaledArg, arg0)
   626  		if result == 0 {
   627  			return 1, false, nil
   628  		}
   629  	}
   630  	return 0, hasNull, nil
   631  }
   632  
   633  type rowFunctionClass struct {
   634  	baseFunctionClass
   635  }
   636  
   637  func (c *rowFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) {
   638  	if err = c.verifyArgs(args); err != nil {
   639  		return nil, err
   640  	}
   641  	argTps := make([]types.EvalType, len(args))
   642  	for i := range argTps {
   643  		argTps[i] = args[i].GetType().EvalType()
   644  	}
   645  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, argTps...)
   646  	if err != nil {
   647  		return nil, err
   648  	}
   649  	sig = &builtinEventSig{bf}
   650  	return sig, nil
   651  }
   652  
   653  type builtinEventSig struct {
   654  	baseBuiltinFunc
   655  }
   656  
   657  func (b *builtinEventSig) Clone() builtinFunc {
   658  	newSig := &builtinEventSig{}
   659  	newSig.cloneFrom(&b.baseBuiltinFunc)
   660  	return newSig
   661  }
   662  
   663  // evalString rowFunc should always be flattened in memex rewrite phrase.
   664  func (b *builtinEventSig) evalString(event chunk.Event) (string, bool, error) {
   665  	panic("builtinEventSig.evalString() should never be called.")
   666  }
   667  
   668  type setVarFunctionClass struct {
   669  	baseFunctionClass
   670  }
   671  
   672  func (c *setVarFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) {
   673  	if err = c.verifyArgs(args); err != nil {
   674  		return nil, err
   675  	}
   676  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString, types.ETString)
   677  	if err != nil {
   678  		return nil, err
   679  	}
   680  	bf.tp.Flen = args[1].GetType().Flen
   681  	// TODO: we should consider the type of the argument, but not take it as string for all situations.
   682  	sig = &builtinSetVarSig{bf}
   683  	return sig, err
   684  }
   685  
   686  type builtinSetVarSig struct {
   687  	baseBuiltinFunc
   688  }
   689  
   690  func (b *builtinSetVarSig) Clone() builtinFunc {
   691  	newSig := &builtinSetVarSig{}
   692  	newSig.cloneFrom(&b.baseBuiltinFunc)
   693  	return newSig
   694  }
   695  
   696  func (b *builtinSetVarSig) evalString(event chunk.Event) (res string, isNull bool, err error) {
   697  	var varName string
   698  	stochastikVars := b.ctx.GetStochastikVars()
   699  	varName, isNull, err = b.args[0].EvalString(b.ctx, event)
   700  	if isNull || err != nil {
   701  		return "", isNull, err
   702  	}
   703  
   704  	causet, err := b.args[1].Eval(event)
   705  	isNull = causet.IsNull()
   706  	if isNull || err != nil {
   707  		return "", isNull, err
   708  	}
   709  
   710  	res, err = causet.ToString()
   711  	if err != nil {
   712  		return "", isNull, err
   713  	}
   714  
   715  	varName = strings.ToLower(varName)
   716  	stochastikVars.UsersLock.Lock()
   717  	stochastikVars.SetUserVar(varName, stringutil.Copy(res), causet.DefCauslation())
   718  	stochastikVars.UsersLock.Unlock()
   719  	return res, false, nil
   720  }
   721  
   722  type getVarFunctionClass struct {
   723  	baseFunctionClass
   724  }
   725  
   726  func (c *getVarFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) {
   727  	if err = c.verifyArgs(args); err != nil {
   728  		return nil, err
   729  	}
   730  	// TODO: we should consider the type of the argument, but not take it as string for all situations.
   731  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString)
   732  	if err != nil {
   733  		return nil, err
   734  	}
   735  	bf.tp.Flen = allegrosql.MaxFieldVarCharLength
   736  	if err := c.resolveDefCauslation(ctx, args, &bf); err != nil {
   737  		return nil, err
   738  	}
   739  	sig = &builtinGetVarSig{bf}
   740  	return sig, nil
   741  }
   742  
   743  func (c *getVarFunctionClass) resolveDefCauslation(ctx stochastikctx.Context, args []Expression, bf *baseBuiltinFunc) (err error) {
   744  	if constant, ok := args[0].(*Constant); ok {
   745  		varName, err := constant.Value.ToString()
   746  		if err != nil {
   747  			return err
   748  		}
   749  		varName = strings.ToLower(varName)
   750  		ctx.GetStochastikVars().UsersLock.RLock()
   751  		defer ctx.GetStochastikVars().UsersLock.RUnlock()
   752  		if v, ok := ctx.GetStochastikVars().Users[varName]; ok {
   753  			bf.tp.DefCauslate = v.DefCauslation()
   754  			if len(bf.tp.Charset) <= 0 {
   755  				charset, _ := ctx.GetStochastikVars().GetCharsetInfo()
   756  				bf.tp.Charset = charset
   757  			}
   758  			return nil
   759  		}
   760  	}
   761  
   762  	return nil
   763  }
   764  
   765  type builtinGetVarSig struct {
   766  	baseBuiltinFunc
   767  }
   768  
   769  func (b *builtinGetVarSig) Clone() builtinFunc {
   770  	newSig := &builtinGetVarSig{}
   771  	newSig.cloneFrom(&b.baseBuiltinFunc)
   772  	return newSig
   773  }
   774  
   775  func (b *builtinGetVarSig) evalString(event chunk.Event) (string, bool, error) {
   776  	stochastikVars := b.ctx.GetStochastikVars()
   777  	varName, isNull, err := b.args[0].EvalString(b.ctx, event)
   778  	if isNull || err != nil {
   779  		return "", isNull, err
   780  	}
   781  	varName = strings.ToLower(varName)
   782  	stochastikVars.UsersLock.RLock()
   783  	defer stochastikVars.UsersLock.RUnlock()
   784  	if v, ok := stochastikVars.Users[varName]; ok {
   785  		return v.GetString(), false, nil
   786  	}
   787  	return "", true, nil
   788  }
   789  
   790  type valuesFunctionClass struct {
   791  	baseFunctionClass
   792  
   793  	offset int
   794  	tp     *types.FieldType
   795  }
   796  
   797  func (c *valuesFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) {
   798  	if err = c.verifyArgs(args); err != nil {
   799  		return nil, err
   800  	}
   801  	bf, err := newBaseBuiltinFunc(ctx, c.funcName, args, c.tp.EvalType())
   802  	if err != nil {
   803  		return nil, err
   804  	}
   805  	bf.tp = c.tp
   806  	switch c.tp.EvalType() {
   807  	case types.ETInt:
   808  		sig = &builtinValuesIntSig{bf, c.offset}
   809  	case types.ETReal:
   810  		sig = &builtinValuesRealSig{bf, c.offset}
   811  	case types.ETDecimal:
   812  		sig = &builtinValuesDecimalSig{bf, c.offset}
   813  	case types.ETString:
   814  		sig = &builtinValuesStringSig{bf, c.offset}
   815  	case types.ETDatetime, types.ETTimestamp:
   816  		sig = &builtinValuesTimeSig{bf, c.offset}
   817  	case types.ETDuration:
   818  		sig = &builtinValuesDurationSig{bf, c.offset}
   819  	case types.ETJson:
   820  		sig = &builtinValuesJSONSig{bf, c.offset}
   821  	}
   822  	return sig, nil
   823  }
   824  
   825  type builtinValuesIntSig struct {
   826  	baseBuiltinFunc
   827  
   828  	offset int
   829  }
   830  
   831  func (b *builtinValuesIntSig) Clone() builtinFunc {
   832  	newSig := &builtinValuesIntSig{offset: b.offset}
   833  	newSig.cloneFrom(&b.baseBuiltinFunc)
   834  	return newSig
   835  }
   836  
   837  // evalInt evals a builtinValuesIntSig.
   838  // See https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values
   839  func (b *builtinValuesIntSig) evalInt(_ chunk.Event) (int64, bool, error) {
   840  	if !b.ctx.GetStochastikVars().StmtCtx.InInsertStmt {
   841  		return 0, true, nil
   842  	}
   843  	event := b.ctx.GetStochastikVars().CurrInsertValues
   844  	if event.IsEmpty() {
   845  		return 0, true, errors.New("Stochastik current insert values is nil")
   846  	}
   847  	if b.offset < event.Len() {
   848  		if event.IsNull(b.offset) {
   849  			return 0, true, nil
   850  		}
   851  		// For BinaryLiteral, see issue #15310
   852  		val := event.GetRaw(b.offset)
   853  		if len(val) > 8 {
   854  			return 0, true, errors.New("Stochastik current insert values is too long")
   855  		}
   856  		if len(val) < 8 {
   857  			var binary types.BinaryLiteral = val
   858  			v, err := binary.ToInt(b.ctx.GetStochastikVars().StmtCtx)
   859  			if err != nil {
   860  				return 0, true, errors.Trace(err)
   861  			}
   862  			return int64(v), false, nil
   863  		}
   864  		return event.GetInt64(b.offset), false, nil
   865  	}
   866  	return 0, true, errors.Errorf("Stochastik current insert values len %d and defCausumn's offset %v don't match", event.Len(), b.offset)
   867  }
   868  
   869  type builtinValuesRealSig struct {
   870  	baseBuiltinFunc
   871  
   872  	offset int
   873  }
   874  
   875  func (b *builtinValuesRealSig) Clone() builtinFunc {
   876  	newSig := &builtinValuesRealSig{offset: b.offset}
   877  	newSig.cloneFrom(&b.baseBuiltinFunc)
   878  	return newSig
   879  }
   880  
   881  // evalReal evals a builtinValuesRealSig.
   882  // See https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values
   883  func (b *builtinValuesRealSig) evalReal(_ chunk.Event) (float64, bool, error) {
   884  	if !b.ctx.GetStochastikVars().StmtCtx.InInsertStmt {
   885  		return 0, true, nil
   886  	}
   887  	event := b.ctx.GetStochastikVars().CurrInsertValues
   888  	if event.IsEmpty() {
   889  		return 0, true, errors.New("Stochastik current insert values is nil")
   890  	}
   891  	if b.offset < event.Len() {
   892  		if event.IsNull(b.offset) {
   893  			return 0, true, nil
   894  		}
   895  		if b.getRetTp().Tp == allegrosql.TypeFloat {
   896  			return float64(event.GetFloat32(b.offset)), false, nil
   897  		}
   898  		return event.GetFloat64(b.offset), false, nil
   899  	}
   900  	return 0, true, errors.Errorf("Stochastik current insert values len %d and defCausumn's offset %v don't match", event.Len(), b.offset)
   901  }
   902  
   903  type builtinValuesDecimalSig struct {
   904  	baseBuiltinFunc
   905  
   906  	offset int
   907  }
   908  
   909  func (b *builtinValuesDecimalSig) Clone() builtinFunc {
   910  	newSig := &builtinValuesDecimalSig{offset: b.offset}
   911  	newSig.cloneFrom(&b.baseBuiltinFunc)
   912  	return newSig
   913  }
   914  
   915  // evalDecimal evals a builtinValuesDecimalSig.
   916  // See https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values
   917  func (b *builtinValuesDecimalSig) evalDecimal(_ chunk.Event) (*types.MyDecimal, bool, error) {
   918  	if !b.ctx.GetStochastikVars().StmtCtx.InInsertStmt {
   919  		return nil, true, nil
   920  	}
   921  	event := b.ctx.GetStochastikVars().CurrInsertValues
   922  	if event.IsEmpty() {
   923  		return nil, true, errors.New("Stochastik current insert values is nil")
   924  	}
   925  	if b.offset < event.Len() {
   926  		if event.IsNull(b.offset) {
   927  			return nil, true, nil
   928  		}
   929  		return event.GetMyDecimal(b.offset), false, nil
   930  	}
   931  	return nil, true, errors.Errorf("Stochastik current insert values len %d and defCausumn's offset %v don't match", event.Len(), b.offset)
   932  }
   933  
   934  type builtinValuesStringSig struct {
   935  	baseBuiltinFunc
   936  
   937  	offset int
   938  }
   939  
   940  func (b *builtinValuesStringSig) Clone() builtinFunc {
   941  	newSig := &builtinValuesStringSig{offset: b.offset}
   942  	newSig.cloneFrom(&b.baseBuiltinFunc)
   943  	return newSig
   944  }
   945  
   946  // evalString evals a builtinValuesStringSig.
   947  // See https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values
   948  func (b *builtinValuesStringSig) evalString(_ chunk.Event) (string, bool, error) {
   949  	if !b.ctx.GetStochastikVars().StmtCtx.InInsertStmt {
   950  		return "", true, nil
   951  	}
   952  	event := b.ctx.GetStochastikVars().CurrInsertValues
   953  	if event.IsEmpty() {
   954  		return "", true, errors.New("Stochastik current insert values is nil")
   955  	}
   956  	if b.offset >= event.Len() {
   957  		return "", true, errors.Errorf("Stochastik current insert values len %d and defCausumn's offset %v don't match", event.Len(), b.offset)
   958  	}
   959  
   960  	if event.IsNull(b.offset) {
   961  		return "", true, nil
   962  	}
   963  
   964  	// Specially handle the ENUM/SET/BIT input value.
   965  	if retType := b.getRetTp(); retType.Hybrid() {
   966  		val := event.GetCauset(b.offset, retType)
   967  		res, err := val.ToString()
   968  		return res, err != nil, err
   969  	}
   970  
   971  	return event.GetString(b.offset), false, nil
   972  }
   973  
   974  type builtinValuesTimeSig struct {
   975  	baseBuiltinFunc
   976  
   977  	offset int
   978  }
   979  
   980  func (b *builtinValuesTimeSig) Clone() builtinFunc {
   981  	newSig := &builtinValuesTimeSig{offset: b.offset}
   982  	newSig.cloneFrom(&b.baseBuiltinFunc)
   983  	return newSig
   984  }
   985  
   986  // evalTime evals a builtinValuesTimeSig.
   987  // See https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values
   988  func (b *builtinValuesTimeSig) evalTime(_ chunk.Event) (types.Time, bool, error) {
   989  	if !b.ctx.GetStochastikVars().StmtCtx.InInsertStmt {
   990  		return types.ZeroTime, true, nil
   991  	}
   992  	event := b.ctx.GetStochastikVars().CurrInsertValues
   993  	if event.IsEmpty() {
   994  		return types.ZeroTime, true, errors.New("Stochastik current insert values is nil")
   995  	}
   996  	if b.offset < event.Len() {
   997  		if event.IsNull(b.offset) {
   998  			return types.ZeroTime, true, nil
   999  		}
  1000  		return event.GetTime(b.offset), false, nil
  1001  	}
  1002  	return types.ZeroTime, true, errors.Errorf("Stochastik current insert values len %d and defCausumn's offset %v don't match", event.Len(), b.offset)
  1003  }
  1004  
  1005  type builtinValuesDurationSig struct {
  1006  	baseBuiltinFunc
  1007  
  1008  	offset int
  1009  }
  1010  
  1011  func (b *builtinValuesDurationSig) Clone() builtinFunc {
  1012  	newSig := &builtinValuesDurationSig{offset: b.offset}
  1013  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1014  	return newSig
  1015  }
  1016  
  1017  // evalDuration evals a builtinValuesDurationSig.
  1018  // See https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values
  1019  func (b *builtinValuesDurationSig) evalDuration(_ chunk.Event) (types.Duration, bool, error) {
  1020  	if !b.ctx.GetStochastikVars().StmtCtx.InInsertStmt {
  1021  		return types.Duration{}, true, nil
  1022  	}
  1023  	event := b.ctx.GetStochastikVars().CurrInsertValues
  1024  	if event.IsEmpty() {
  1025  		return types.Duration{}, true, errors.New("Stochastik current insert values is nil")
  1026  	}
  1027  	if b.offset < event.Len() {
  1028  		if event.IsNull(b.offset) {
  1029  			return types.Duration{}, true, nil
  1030  		}
  1031  		duration := event.GetDuration(b.offset, b.getRetTp().Decimal)
  1032  		return duration, false, nil
  1033  	}
  1034  	return types.Duration{}, true, errors.Errorf("Stochastik current insert values len %d and defCausumn's offset %v don't match", event.Len(), b.offset)
  1035  }
  1036  
  1037  type builtinValuesJSONSig struct {
  1038  	baseBuiltinFunc
  1039  
  1040  	offset int
  1041  }
  1042  
  1043  func (b *builtinValuesJSONSig) Clone() builtinFunc {
  1044  	newSig := &builtinValuesJSONSig{offset: b.offset}
  1045  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1046  	return newSig
  1047  }
  1048  
  1049  // evalJSON evals a builtinValuesJSONSig.
  1050  // See https://dev.allegrosql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values
  1051  func (b *builtinValuesJSONSig) evalJSON(_ chunk.Event) (json.BinaryJSON, bool, error) {
  1052  	if !b.ctx.GetStochastikVars().StmtCtx.InInsertStmt {
  1053  		return json.BinaryJSON{}, true, nil
  1054  	}
  1055  	event := b.ctx.GetStochastikVars().CurrInsertValues
  1056  	if event.IsEmpty() {
  1057  		return json.BinaryJSON{}, true, errors.New("Stochastik current insert values is nil")
  1058  	}
  1059  	if b.offset < event.Len() {
  1060  		if event.IsNull(b.offset) {
  1061  			return json.BinaryJSON{}, true, nil
  1062  		}
  1063  		return event.GetJSON(b.offset), false, nil
  1064  	}
  1065  	return json.BinaryJSON{}, true, errors.Errorf("Stochastik current insert values len %d and defCausumn's offset %v don't match", event.Len(), b.offset)
  1066  }
  1067  
  1068  type bitCountFunctionClass struct {
  1069  	baseFunctionClass
  1070  }
  1071  
  1072  func (c *bitCountFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  1073  	if err := c.verifyArgs(args); err != nil {
  1074  		return nil, err
  1075  	}
  1076  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETInt)
  1077  	if err != nil {
  1078  		return nil, err
  1079  	}
  1080  	bf.tp.Flen = 2
  1081  	sig := &builtinBitCountSig{bf}
  1082  	return sig, nil
  1083  }
  1084  
  1085  type builtinBitCountSig struct {
  1086  	baseBuiltinFunc
  1087  }
  1088  
  1089  func (b *builtinBitCountSig) Clone() builtinFunc {
  1090  	newSig := &builtinBitCountSig{}
  1091  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1092  	return newSig
  1093  }
  1094  
  1095  // evalInt evals BIT_COUNT(N).
  1096  // See https://dev.allegrosql.com/doc/refman/5.7/en/bit-functions.html#function_bit-count
  1097  func (b *builtinBitCountSig) evalInt(event chunk.Event) (int64, bool, error) {
  1098  	n, isNull, err := b.args[0].EvalInt(b.ctx, event)
  1099  	if err != nil || isNull {
  1100  		if err != nil && types.ErrOverflow.Equal(err) {
  1101  			return 64, false, nil
  1102  		}
  1103  		return 0, true, err
  1104  	}
  1105  	return bitCount(n), false, nil
  1106  }
  1107  
  1108  // getParamFunctionClass for plan cache of prepared memexs
  1109  type getParamFunctionClass struct {
  1110  	baseFunctionClass
  1111  }
  1112  
  1113  // getFunction gets function
  1114  // TODO: more typed functions will be added when typed parameters are supported.
  1115  func (c *getParamFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) {
  1116  	if err := c.verifyArgs(args); err != nil {
  1117  		return nil, err
  1118  	}
  1119  	bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETInt)
  1120  	if err != nil {
  1121  		return nil, err
  1122  	}
  1123  	bf.tp.Flen = allegrosql.MaxFieldVarCharLength
  1124  	sig := &builtinGetParamStringSig{bf}
  1125  	return sig, nil
  1126  }
  1127  
  1128  type builtinGetParamStringSig struct {
  1129  	baseBuiltinFunc
  1130  }
  1131  
  1132  func (b *builtinGetParamStringSig) Clone() builtinFunc {
  1133  	newSig := &builtinGetParamStringSig{}
  1134  	newSig.cloneFrom(&b.baseBuiltinFunc)
  1135  	return newSig
  1136  }
  1137  
  1138  func (b *builtinGetParamStringSig) evalString(event chunk.Event) (string, bool, error) {
  1139  	stochastikVars := b.ctx.GetStochastikVars()
  1140  	idx, isNull, err := b.args[0].EvalInt(b.ctx, event)
  1141  	if isNull || err != nil {
  1142  		return "", isNull, err
  1143  	}
  1144  	v := stochastikVars.PreparedParams[idx]
  1145  
  1146  	str, err := v.ToString()
  1147  	if err != nil {
  1148  		return "", true, nil
  1149  	}
  1150  	return str, false, nil
  1151  }