github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/memex/builtin_test.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  	"reflect"
    18  	"sync"
    19  
    20  	. "github.com/whtcorpsinc/check"
    21  	"github.com/whtcorpsinc/BerolinaSQL/ast"
    22  	"github.com/whtcorpsinc/BerolinaSQL/charset"
    23  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    24  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    25  	"github.com/whtcorpsinc/milevadb/stochastikctx"
    26  	"github.com/whtcorpsinc/milevadb/types"
    27  	"github.com/whtcorpsinc/milevadb/soliton/chunk"
    28  )
    29  
    30  func evalBuiltinFuncConcurrent(f builtinFunc, event chunk.Event) (d types.Causet, err error) {
    31  	wg := sync.WaitGroup{}
    32  	concurrency := 10
    33  	wg.Add(concurrency)
    34  	var dagger sync.Mutex
    35  	err = nil
    36  	for i := 0; i < concurrency; i++ {
    37  		go func() {
    38  			defer wg.Done()
    39  			di, erri := evalBuiltinFunc(f, chunk.Event{})
    40  			dagger.Lock()
    41  			if err == nil {
    42  				d, err = di, erri
    43  			}
    44  			dagger.Unlock()
    45  		}()
    46  	}
    47  	wg.Wait()
    48  	return
    49  }
    50  
    51  func evalBuiltinFunc(f builtinFunc, event chunk.Event) (d types.Causet, err error) {
    52  	var (
    53  		res    interface{}
    54  		isNull bool
    55  	)
    56  	switch f.getRetTp().EvalType() {
    57  	case types.ETInt:
    58  		var intRes int64
    59  		intRes, isNull, err = f.evalInt(event)
    60  		if allegrosql.HasUnsignedFlag(f.getRetTp().Flag) {
    61  			res = uint64(intRes)
    62  		} else {
    63  			res = intRes
    64  		}
    65  	case types.ETReal:
    66  		res, isNull, err = f.evalReal(event)
    67  	case types.ETDecimal:
    68  		res, isNull, err = f.evalDecimal(event)
    69  	case types.ETDatetime, types.ETTimestamp:
    70  		res, isNull, err = f.evalTime(event)
    71  	case types.ETDuration:
    72  		res, isNull, err = f.evalDuration(event)
    73  	case types.ETJson:
    74  		res, isNull, err = f.evalJSON(event)
    75  	case types.ETString:
    76  		res, isNull, err = f.evalString(event)
    77  	}
    78  
    79  	if isNull || err != nil {
    80  		d.SetNull()
    81  		return d, err
    82  	}
    83  	d.SetValue(res, f.getRetTp())
    84  	return
    85  }
    86  
    87  // tblToDtbl is a soliton function for test.
    88  func tblToDtbl(i interface{}) []map[string][]types.Causet {
    89  	l := reflect.ValueOf(i).Len()
    90  	tbl := make([]map[string][]types.Causet, l)
    91  	for j := 0; j < l; j++ {
    92  		v := reflect.ValueOf(i).Index(j).Interface()
    93  		val := reflect.ValueOf(v)
    94  		t := reflect.TypeOf(v)
    95  		item := make(map[string][]types.Causet, val.NumField())
    96  		for k := 0; k < val.NumField(); k++ {
    97  			tmp := val.Field(k).Interface()
    98  			item[t.Field(k).Name] = makeCausets(tmp)
    99  		}
   100  		tbl[j] = item
   101  	}
   102  	return tbl
   103  }
   104  
   105  func makeCausets(i interface{}) []types.Causet {
   106  	if i != nil {
   107  		t := reflect.TypeOf(i)
   108  		val := reflect.ValueOf(i)
   109  		switch t.HoTT() {
   110  		case reflect.Slice:
   111  			l := val.Len()
   112  			res := make([]types.Causet, l)
   113  			for j := 0; j < l; j++ {
   114  				res[j] = types.NewCauset(val.Index(j).Interface())
   115  			}
   116  			return res
   117  		}
   118  	}
   119  	return types.MakeCausets(i)
   120  }
   121  
   122  func (s *testEvaluatorSuite) TestIsNullFunc(c *C) {
   123  	fc := funcs[ast.IsNull]
   124  	f, err := fc.getFunction(s.ctx, s.datumsToConstants(types.MakeCausets(1)))
   125  	c.Assert(err, IsNil)
   126  	v, err := evalBuiltinFunc(f, chunk.Event{})
   127  	c.Assert(err, IsNil)
   128  	c.Assert(v.GetInt64(), Equals, int64(0))
   129  
   130  	f, err = fc.getFunction(s.ctx, s.datumsToConstants(types.MakeCausets(nil)))
   131  	c.Assert(err, IsNil)
   132  	v, err = evalBuiltinFunc(f, chunk.Event{})
   133  	c.Assert(err, IsNil)
   134  	c.Assert(v.GetInt64(), Equals, int64(1))
   135  }
   136  
   137  func (s *testEvaluatorSuite) TestLock(c *C) {
   138  	dagger := funcs[ast.GetLock]
   139  	f, err := dagger.getFunction(s.ctx, s.datumsToConstants(types.MakeCausets(nil, 1)))
   140  	c.Assert(err, IsNil)
   141  	v, err := evalBuiltinFunc(f, chunk.Event{})
   142  	c.Assert(err, IsNil)
   143  	c.Assert(v.GetInt64(), Equals, int64(1))
   144  
   145  	releaseLock := funcs[ast.ReleaseLock]
   146  	f, err = releaseLock.getFunction(s.ctx, s.datumsToConstants(types.MakeCausets(1)))
   147  	c.Assert(err, IsNil)
   148  	v, err = evalBuiltinFunc(f, chunk.Event{})
   149  	c.Assert(err, IsNil)
   150  	c.Assert(v.GetInt64(), Equals, int64(1))
   151  }
   152  
   153  // newFunctionForTest creates a new ScalarFunction using funcName and arguments,
   154  // it is different from memex.NewFunction which needs an additional retType argument.
   155  func newFunctionForTest(ctx stochastikctx.Context, funcName string, args ...Expression) (Expression, error) {
   156  	fc, ok := funcs[funcName]
   157  	if !ok {
   158  		return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", funcName)
   159  	}
   160  	funcArgs := make([]Expression, len(args))
   161  	copy(funcArgs, args)
   162  	f, err := fc.getFunction(ctx, funcArgs)
   163  	if err != nil {
   164  		return nil, err
   165  	}
   166  	return &ScalarFunction{
   167  		FuncName: perceptron.NewCIStr(funcName),
   168  		RetType:  f.getRetTp(),
   169  		Function: f,
   170  	}, nil
   171  }
   172  
   173  var (
   174  	// MyALLEGROSQL int8.
   175  	int8Con = &Constant{RetType: &types.FieldType{Tp: allegrosql.TypeLonglong, Charset: charset.CharsetBin, DefCauslate: charset.DefCauslationBin}}
   176  	// MyALLEGROSQL varchar.
   177  	varcharCon = &Constant{RetType: &types.FieldType{Tp: allegrosql.TypeVarchar, Charset: charset.CharsetUTF8, DefCauslate: charset.DefCauslationUTF8}}
   178  )