github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/memex/generator/control_vec.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  // +build ignore
    15  
    16  package main
    17  
    18  import (
    19  	"bytes"
    20  	"go/format"
    21  	"io/ioutil"
    22  	"log"
    23  	"path/filepath"
    24  	"text/template"
    25  
    26  	. "github.com/whtcorpsinc/milevadb/memex/generator/helper"
    27  )
    28  
    29  const header = `// Copyright 2020 WHTCORPS INC, Inc.
    30  //
    31  // Licensed under the Apache License, Version 2.0 (the "License");
    32  // you may not use this file except in compliance with the License.
    33  // You may obtain a copy of the License at
    34  //
    35  //     http://www.apache.org/licenses/LICENSE-2.0
    36  //
    37  // Unless required by applicable law or agreed to in writing, software
    38  // distributed under the License is distributed on an "AS IS" BASIS,
    39  // See the License for the specific language governing permissions and
    40  // limitations under the License.
    41  
    42  // Code generated by go generate in memex/generator; DO NOT EDIT.
    43  
    44  package memex
    45  
    46  import (
    47  	"time"
    48  
    49  	"github.com/whtcorpsinc/milevadb/types"
    50  	"github.com/whtcorpsinc/milevadb/soliton/chunk"
    51  )
    52  
    53  // NOTE: Control memexs optionally evaluate some branches depending on conditions, but vectorization executes all
    54  // branches, during which the unnecessary branches may return errors or warnings. To avoid this case, when branches 
    55  // meet errors or warnings, the vectorization falls back the scalar execution.
    56  
    57  `
    58  
    59  var builtinCaseWhenVec = template.Must(template.New("builtinCaseWhenVec").Parse(`
    60  {{ range .Sigs }}{{ with .Arg0 }}
    61  func (b *builtinCaseWhen{{ .TypeName }}Sig) fallbackEval{{ .TypeName }}(input *chunk.Chunk, result *chunk.DeferredCauset) error {
    62  	n := input.NumEvents()
    63  	{{- if .Fixed }}
    64  	result.Resize{{ .TypeNameInDeferredCauset }}(n, false)
    65  	x := result.{{ .TypeNameInDeferredCauset }}s()
    66  	for i := 0; i < n; i++ {
    67  		res, isNull, err := b.eval{{ .TypeName }}(input.GetEvent(i))
    68  		if err != nil {
    69  			return err
    70  		}
    71  		result.SetNull(i, isNull)
    72  		if isNull {
    73  			continue
    74  		}
    75  		{{ if eq .TypeName "Decimal" }}
    76  			x[i] = *res
    77  		{{ else if eq .TypeName "Duration" }}
    78  			x[i] = res.Duration
    79  		{{ else }}
    80  			x[i] = res
    81  		{{ end }}
    82  	}
    83  	{{ else }}
    84  	result.Reserve{{ .TypeNameInDeferredCauset }}(n)
    85  	for i := 0; i < n; i++ {
    86  		res, isNull, err := b.eval{{ .TypeName }}(input.GetEvent(i))
    87  		if err != nil {
    88  			return err
    89  		}
    90  		if isNull {
    91  			result.AppendNull()
    92  			continue
    93  		}
    94  		result.Append{{ .TypeNameInDeferredCauset }}(res)
    95  	}
    96  	{{ end -}}
    97  	return nil
    98  }
    99  
   100  func (b *builtinCaseWhen{{ .TypeName }}Sig) vecEval{{ .TypeName }}(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   101  	n := input.NumEvents()
   102  	args, l := b.getArgs(), len(b.getArgs())
   103  	whens := make([]*chunk.DeferredCauset, l/2)
   104  	whensSlice := make([][]int64, l/2)
   105  	thens := make([]*chunk.DeferredCauset, l/2)
   106  	var eLse *chunk.DeferredCauset
   107  	{{- if .Fixed }}
   108  	thensSlice := make([][]{{.TypeNameGo}}, l/2)
   109  	var eLseSlice []{{.TypeNameGo}}
   110  	{{- end }}
   111  	sc := b.ctx.GetStochastikVars().StmtCtx
   112  	beforeWarns := sc.WarningCount()
   113  
   114  	for j := 0; j < l-1; j+=2 {
   115  		bufWhen, err := b.bufSlabPredictor.get(types.ETInt, n)
   116  		if err != nil {
   117  			return err
   118  		}
   119  		defer b.bufSlabPredictor.put(bufWhen)
   120  		err = args[j].VecEvalInt(b.ctx, input, bufWhen)
   121  		afterWarns := sc.WarningCount()
   122  		if err != nil || afterWarns > beforeWarns {
   123  			if afterWarns > beforeWarns {
   124  				sc.TruncateWarnings(int(beforeWarns))
   125  			}
   126  			return b.fallbackEval{{ .TypeName }}(input, result)
   127  		}
   128  		whens[j/2] = bufWhen
   129  		whensSlice[j/2] = bufWhen.Int64s()
   130  
   131  		bufThen, err := b.bufSlabPredictor.get(types.ET{{ .ETName }}, n)
   132  		if err != nil {
   133  			return err
   134  		}
   135  		defer b.bufSlabPredictor.put(bufThen)
   136  		err = args[j+1].VecEval{{ .TypeName }}(b.ctx, input, bufThen)
   137  		afterWarns = sc.WarningCount()
   138  		if err != nil || afterWarns > beforeWarns {
   139  			if afterWarns > beforeWarns {
   140  				sc.TruncateWarnings(int(beforeWarns))
   141  			}
   142  			return b.fallbackEval{{ .TypeName }}(input, result)
   143  		}
   144  		thens[j/2] = bufThen
   145  		{{- if .Fixed }}
   146  		thensSlice[j/2] = bufThen.{{ .TypeNameInDeferredCauset }}s()
   147  		{{- end }}
   148  	}
   149  	// when clause(condition, result) -> args[i], args[i+1]; (i >= 0 && i+1 < l-1)
   150  	// else clause -> args[l-1]
   151  	// If case clause has else clause, l%2 == 1.
   152  	if l%2==1 {
   153  		bufElse, err := b.bufSlabPredictor.get(types.ET{{ .ETName }}, n)
   154  		if err != nil {
   155  			return err
   156  		}
   157  		defer b.bufSlabPredictor.put(bufElse)
   158  		err = args[l-1].VecEval{{ .TypeName }}(b.ctx, input, bufElse)
   159  		afterWarns := sc.WarningCount()
   160  		if err != nil || afterWarns > beforeWarns {
   161  			if afterWarns > beforeWarns {
   162  				sc.TruncateWarnings(int(beforeWarns))
   163  			}
   164  			return b.fallbackEval{{ .TypeName }}(input, result)
   165  		}
   166  		eLse = bufElse
   167  		{{- if .Fixed }}
   168  		eLseSlice = bufElse.{{ .TypeNameInDeferredCauset }}s()
   169  		{{- end }}
   170  	}
   171  	
   172  	{{- if .Fixed }}
   173  	result.Resize{{ .TypeNameInDeferredCauset }}(n, false)
   174  	resultSlice := result.{{ .TypeNameInDeferredCauset }}s()
   175  	{{- else }}
   176  	result.Reserve{{ .TypeNameInDeferredCauset }}(n)
   177  	{{- end }}		
   178  ROW:
   179  	for i := 0; i < n; i++ {
   180  		for j := 0; j < l/2; j++ {
   181  			if whens[j].IsNull(i) || whensSlice[j][i] == 0 {
   182  				continue
   183  			}
   184  			{{- if .Fixed }}
   185  			resultSlice[i] = thensSlice[j][i]
   186  			result.SetNull(i, thens[j].IsNull(i))
   187  			{{- else }}
   188  			if thens[j].IsNull(i) {
   189  				result.AppendNull()
   190  			} else {
   191  				result.Append{{ .TypeNameInDeferredCauset }}(thens[j].Get{{ .TypeNameInDeferredCauset }}(i))
   192  			}
   193  			{{- end }}
   194  			continue ROW
   195  		}
   196  		if eLse != nil {
   197  			{{- if .Fixed }}
   198  			resultSlice[i] = eLseSlice[i]
   199  			result.SetNull(i, eLse.IsNull(i))
   200  			{{- else }}
   201  			if eLse.IsNull(i) {
   202  				result.AppendNull()
   203  			} else {
   204  				result.Append{{ .TypeNameInDeferredCauset }}(eLse.Get{{ .TypeNameInDeferredCauset }}(i))
   205  			}	
   206  			{{- end }}
   207  		} else {
   208  			{{- if .Fixed }}
   209  			result.SetNull(i, true)
   210  			{{- else }}
   211  			result.AppendNull()
   212  			{{- end }}
   213  		}
   214  	}
   215  	return nil
   216  }
   217  
   218  func (b *builtinCaseWhen{{ .TypeName }}Sig) vectorized() bool {
   219  	return true
   220  }
   221  {{ end }}{{/* with */}}
   222  {{ end }}{{/* range .Sigs */}}
   223  `))
   224  
   225  var builtinIfNullVec = template.Must(template.New("builtinIfNullVec").Parse(`
   226  {{ range .Sigs }}{{ with .Arg0 }}
   227  func (b *builtinIfNull{{ .TypeName }}Sig) fallbackEval{{ .TypeName }}(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   228  	n := input.NumEvents()
   229  	{{- if .Fixed }}
   230  	x := result.{{ .TypeNameInDeferredCauset }}s()
   231  	for i := 0; i < n; i++ {
   232  		res, isNull, err := b.eval{{ .TypeName }}(input.GetEvent(i))
   233  		if err != nil {
   234  			return err
   235  		}
   236  		result.SetNull(i, isNull)
   237  		if isNull {
   238  			continue
   239  		}
   240  		{{ if eq .TypeName "Decimal" }}
   241  			x[i] = *res
   242  		{{ else if eq .TypeName "Duration" }}
   243  			x[i] = res.Duration
   244  		{{ else }}
   245  			x[i] = res
   246  		{{ end }}
   247  	}
   248  	{{ else }}
   249  	result.Reserve{{ .TypeNameInDeferredCauset }}(n)
   250  	for i := 0; i < n; i++ {
   251  		res, isNull, err := b.eval{{ .TypeName }}(input.GetEvent(i))
   252  		if err != nil {
   253  			return err
   254  		}
   255  		if isNull {
   256  			result.AppendNull()
   257  			continue
   258  		}
   259  		result.Append{{ .TypeNameInDeferredCauset }}(res)
   260  	}
   261  	{{ end -}}
   262  	return nil
   263  }
   264  
   265  func (b *builtinIfNull{{ .TypeName }}Sig) vecEval{{ .TypeName }}(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   266  	n := input.NumEvents()
   267  	{{- if .Fixed }}
   268  	if err := b.args[0].VecEval{{ .TypeName }}(b.ctx, input, result); err != nil {
   269  		return err
   270  	}
   271  	buf1, err := b.bufSlabPredictor.get(types.ET{{ .ETName }}, n)
   272  	if err != nil {
   273  		return err
   274  	}
   275  	defer b.bufSlabPredictor.put(buf1)
   276  	sc := b.ctx.GetStochastikVars().StmtCtx
   277  	beforeWarns := sc.WarningCount()
   278  	err = b.args[1].VecEval{{ .TypeName }}(b.ctx, input, buf1)
   279  	afterWarns := sc.WarningCount()
   280  	if err != nil || afterWarns > beforeWarns {
   281  		if afterWarns > beforeWarns {
   282        		sc.TruncateWarnings(int(beforeWarns))
   283  		}
   284        	return b.fallbackEval{{ .TypeName }}(input, result)
   285     	}
   286  	arg0 := result.{{ .TypeNameInDeferredCauset }}s()
   287  	arg1 := buf1.{{ .TypeNameInDeferredCauset }}s()
   288  	for i := 0; i < n; i++ {
   289  		if result.IsNull(i) && !buf1.IsNull(i) {
   290  			result.SetNull(i, false)
   291  			arg0[i] = arg1[i]
   292  		}
   293  	}
   294  	{{ else }}
   295  	buf0, err := b.bufSlabPredictor.get(types.ET{{ .ETName }}, n)
   296  	if err != nil {
   297  		return err
   298  	}
   299  	defer b.bufSlabPredictor.put(buf0)
   300  	if err := b.args[0].VecEval{{ .TypeName }}(b.ctx, input, buf0); err != nil {
   301  		return err
   302  	}
   303  	buf1, err := b.bufSlabPredictor.get(types.ET{{ .ETName }}, n)
   304  	if err != nil {
   305  		return err
   306  	}
   307  	defer b.bufSlabPredictor.put(buf1)
   308  	sc := b.ctx.GetStochastikVars().StmtCtx
   309  	beforeWarns := sc.WarningCount()
   310  	err = b.args[1].VecEval{{ .TypeName }}(b.ctx, input, buf1)
   311  	afterWarns := sc.WarningCount()
   312  	if err != nil || afterWarns > beforeWarns {
   313  		if afterWarns > beforeWarns {
   314        		sc.TruncateWarnings(int(beforeWarns))
   315  		}
   316        	return b.fallbackEval{{ .TypeName }}(input,result)
   317     	}
   318  
   319  	result.Reserve{{ .TypeNameInDeferredCauset }}(n)
   320  	for i := 0; i < n; i++ {
   321  		if !buf0.IsNull(i) {
   322  			result.Append{{ .TypeNameInDeferredCauset }}(buf0.Get{{ .TypeNameInDeferredCauset }}(i))
   323  		} else if !buf1.IsNull(i) {
   324  			result.Append{{ .TypeNameInDeferredCauset }}(buf1.Get{{ .TypeNameInDeferredCauset }}(i))
   325  		} else {
   326  			result.AppendNull()
   327  		}
   328  	}
   329  	{{ end -}}
   330  	return nil
   331  }
   332  
   333  func (b *builtinIfNull{{ .TypeName }}Sig) vectorized() bool {
   334  	return true
   335  }
   336  {{ end }}{{/* with */}}
   337  {{ end }}{{/* range .Sigs */}}
   338  `))
   339  
   340  var builtinIfVec = template.Must(template.New("builtinIfVec").Parse(`
   341  {{ range .Sigs }}{{ with .Arg0 }}
   342  func (b *builtinIf{{ .TypeName }}Sig) fallbackEval{{ .TypeName }}(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   343  	n := input.NumEvents()
   344  	{{- if .Fixed }}
   345  	x := result.{{ .TypeNameInDeferredCauset }}s()
   346  	for i := 0; i < n; i++ {
   347  		res, isNull, err := b.eval{{ .TypeName }}(input.GetEvent(i))
   348  		if err != nil {
   349  			return err
   350  		}
   351  		result.SetNull(i, isNull)
   352  		if isNull {
   353  			continue
   354  		}
   355  		{{ if eq .TypeName "Decimal" }}
   356  			x[i] = *res
   357  		{{ else if eq .TypeName "Duration" }}
   358  			x[i] = res.Duration
   359  		{{ else }}
   360  			x[i] = res
   361  		{{ end }}
   362  	}
   363  	{{ else }}
   364  	result.Reserve{{ .TypeNameInDeferredCauset }}(n)
   365  	for i := 0; i < n; i++ {
   366  		res, isNull, err := b.eval{{ .TypeName }}(input.GetEvent(i))
   367  		if err != nil {
   368  			return err
   369  		}
   370  		if isNull {
   371  			result.AppendNull()
   372  			continue
   373  		}
   374  		result.Append{{ .TypeNameInDeferredCauset }}(res)
   375  	}
   376  	{{ end -}}
   377  	return nil
   378  }
   379  
   380  func (b *builtinIf{{ .TypeName }}Sig) vecEval{{ .TypeName }}(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   381  	n := input.NumEvents()
   382  	buf0, err := b.bufSlabPredictor.get(types.ETInt, n)
   383  	if err != nil {
   384  		return err
   385  	}
   386  	defer b.bufSlabPredictor.put(buf0)
   387  	if err := b.args[0].VecEvalInt(b.ctx, input, buf0); err != nil {
   388  		return err
   389  	}
   390  	sc := b.ctx.GetStochastikVars().StmtCtx
   391  	beforeWarns := sc.WarningCount()
   392  {{- if .Fixed }}
   393  	err = b.args[1].VecEval{{ .TypeName }}(b.ctx, input, result)
   394  {{- else }}
   395  	buf1, err := b.bufSlabPredictor.get(types.ET{{ .ETName }}, n)
   396  	if err != nil {
   397  		return err
   398  	}
   399  	defer b.bufSlabPredictor.put(buf1)
   400  	err = b.args[1].VecEval{{ .TypeName }}(b.ctx, input, buf1)
   401  {{- end }}
   402  	afterWarns := sc.WarningCount()
   403  	if err != nil || afterWarns > beforeWarns {
   404  		if afterWarns > beforeWarns {
   405        		sc.TruncateWarnings(int(beforeWarns))
   406  		}
   407        	return b.fallbackEval{{ .TypeName }}(input, result)
   408     	}
   409  	
   410  	buf2, err := b.bufSlabPredictor.get(types.ET{{ .ETName }}, n)
   411  	if err != nil {
   412  		return err
   413  	}
   414  	defer b.bufSlabPredictor.put(buf2)
   415  	err = b.args[2].VecEval{{ .TypeName }}(b.ctx, input, buf2)
   416  	afterWarns = sc.WarningCount()
   417  	if err != nil || afterWarns > beforeWarns {
   418  		if afterWarns > beforeWarns {
   419        		sc.TruncateWarnings(int(beforeWarns))
   420  		}
   421        	return b.fallbackEval{{ .TypeName }}(input, result)
   422     	}
   423  {{ if not .Fixed }}
   424  	result.Reserve{{ .TypeNameInDeferredCauset }}(n)
   425  {{- end }}
   426  	arg0 := buf0.Int64s()
   427  {{- if .Fixed }}
   428  	arg2 := buf2.{{ .TypeNameInDeferredCauset }}s()
   429  	rs := result.{{ .TypeNameInDeferredCauset }}s()
   430  {{- end }}
   431  	for i := 0; i < n; i++ {
   432  		arg := arg0[i]
   433  		isNull0 := buf0.IsNull(i)
   434  		switch {
   435  		case isNull0 || arg == 0:
   436  {{- if .Fixed }}
   437  			if buf2.IsNull(i) {
   438  				result.SetNull(i, true)
   439  			} else {
   440  				result.SetNull(i, false)
   441  				rs[i] = arg2[i]
   442  			}
   443  {{- else }}
   444  			if buf2.IsNull(i) {
   445  				result.AppendNull()
   446  			} else {
   447  				result.Append{{ .TypeNameInDeferredCauset }}(buf2.Get{{ .TypeNameInDeferredCauset }}(i))
   448  			}
   449  {{- end }}
   450  		case arg != 0:
   451  {{- if .Fixed }}
   452  {{- else }}
   453  			if buf1.IsNull(i) {
   454  				result.AppendNull()
   455  			} else {
   456  				result.Append{{ .TypeNameInDeferredCauset }}(buf1.Get{{ .TypeNameInDeferredCauset }}(i))
   457  			}
   458  {{- end }}
   459  		}
   460  	}
   461  	return nil
   462  }
   463  
   464  func (b *builtinIf{{ .TypeName }}Sig) vectorized() bool {
   465  	return true
   466  }
   467  {{ end }}{{/* with */}}
   468  {{ end }}{{/* range .Sigs */}}
   469  `))
   470  
   471  var testFile = template.Must(template.New("testFile").Parse(`// Copyright 2020 WHTCORPS INC, Inc.
   472  //
   473  // Licensed under the Apache License, Version 2.0 (the "License");
   474  // you may not use this file except in compliance with the License.
   475  // You may obtain a copy of the License at
   476  //
   477  //     http://www.apache.org/licenses/LICENSE-2.0
   478  //
   479  // Unless required by applicable law or agreed to in writing, software
   480  // distributed under the License is distributed on an "AS IS" BASIS,
   481  // See the License for the specific language governing permissions and
   482  // limitations under the License.
   483  
   484  // Code generated by go generate in memex/generator; DO NOT EDIT.
   485  
   486  package memex
   487  
   488  import (
   489  	"math/rand"
   490  	"testing"
   491  
   492  	. "github.com/whtcorpsinc/check"
   493  	"github.com/whtcorpsinc/BerolinaSQL/ast"
   494  	"github.com/whtcorpsinc/milevadb/types"
   495  )
   496  
   497  var defaultControlIntGener = &controlIntGener{zeroRation: 0.3, defaultGener: *newDefaultGener(0.3, types.ETInt)}
   498  
   499  type controlIntGener struct {
   500  	zeroRation float64
   501  	defaultGener
   502  }
   503  
   504  func (g *controlIntGener) gen() interface{} {
   505  	if rand.Float64() < g.zeroRation {
   506  		return int64(0)
   507  	}
   508  	return g.defaultGener.gen()
   509  }
   510  
   511  {{/* Add more test cases here if we have more functions in this file */}}
   512  var vecBuiltin{{.Category}}Cases = map[string][]vecExprBenchCase{
   513  {{ with index .Functions 0 }}
   514  	ast.Case: {
   515  	{{ range .Sigs }}
   516  		{retEvalType: types.ET{{ .Arg0.ETName }}, childrenTypes: []types.EvalType{types.ETInt, types.ET{{ .Arg0.ETName }}}, geners: []dataGenerator{defaultControlIntGener}},
   517  		{retEvalType: types.ET{{ .Arg0.ETName }}, childrenTypes: []types.EvalType{types.ETInt, types.ET{{ .Arg0.ETName }}, types.ET{{ .Arg0.ETName }}}, geners: []dataGenerator{defaultControlIntGener}},
   518  		{retEvalType: types.ET{{ .Arg0.ETName }}, childrenTypes: []types.EvalType{types.ETInt, types.ET{{ .Arg0.ETName }}, types.ETInt, types.ET{{ .Arg0.ETName }}}, geners: []dataGenerator{defaultControlIntGener, nil, defaultControlIntGener}},
   519  		{retEvalType: types.ET{{ .Arg0.ETName }}, childrenTypes: []types.EvalType{types.ETInt, types.ET{{ .Arg0.ETName }}, types.ETInt, types.ET{{ .Arg0.ETName }}, types.ET{{ .Arg0.ETName }}}, geners: []dataGenerator{defaultControlIntGener, nil, defaultControlIntGener}},
   520  	{{ end }}
   521  	},
   522  {{ end }}
   523  
   524  {{ with index .Functions 1 }}
   525  	ast.Ifnull: {
   526  	{{ range .Sigs }}
   527  		{retEvalType: types.ET{{ .Arg0.ETName }}, childrenTypes: []types.EvalType{types.ET{{ .Arg0.ETName }}, types.ET{{ .Arg0.ETName }}}},
   528  	{{ end }}
   529  	},
   530  {{ end }}
   531  
   532  {{ with index .Functions 2 }}
   533  	ast.If: {
   534  	{{ range .Sigs }}
   535  		{retEvalType: types.ET{{ .Arg0.ETName }}, childrenTypes: []types.EvalType{types.ETInt, types.ET{{ .Arg0.ETName }}, types.ET{{ .Arg0.ETName }}}, geners: []dataGenerator{defaultControlIntGener}},
   536  	{{ end }}
   537  	},
   538  {{ end }}
   539  }
   540  
   541  func (s *testEvaluatorSuite) TestVectorizedBuiltin{{.Category}}EvalOneVecGenerated(c *C) {
   542  	testVectorizedEvalOneVec(c, vecBuiltinControlCases)
   543  }
   544  
   545  func (s *testEvaluatorSuite) TestVectorizedBuiltin{{.Category}}FuncGenerated(c *C) {
   546  	testVectorizedBuiltinFunc(c, vecBuiltinControlCases)
   547  }
   548  
   549  func BenchmarkVectorizedBuiltin{{.Category}}EvalOneVecGenerated(b *testing.B) {
   550  	benchmarkVectorizedEvalOneVec(b, vecBuiltinControlCases)
   551  }
   552  
   553  func BenchmarkVectorizedBuiltin{{.Category}}FuncGenerated(b *testing.B) {
   554  	benchmarkVectorizedBuiltinFunc(b, vecBuiltinControlCases)
   555  }
   556  `))
   557  
   558  type typeContext struct {
   559  	// Describe the name of "github.com/whtcorpsinc/milevadb/types".ET{{ .ETName }}
   560  	ETName string
   561  	// Describe the name of "github.com/whtcorpsinc/milevadb/memex".VecExpr.VecEval{{ .TypeName }}
   562  	// If undefined, it's same as ETName.
   563  	TypeName string
   564  	// Describe the name of "github.com/whtcorpsinc/milevadb/soliton/chunk".*DeferredCauset.Append{{ .TypeNameInDeferredCauset }},
   565  	// Resize{{ .TypeNameInDeferredCauset }}, Reserve{{ .TypeNameInDeferredCauset }}, Get{{ .TypeNameInDeferredCauset }} and
   566  	// {{ .TypeNameInDeferredCauset }}s.
   567  	// If undefined, it's same as TypeName.
   568  	TypeNameInDeferredCauset string
   569  	// Same as "github.com/whtcorpsinc/milevadb/soliton/chunk".getFixedLen()
   570  	Fixed bool
   571  }
   572  
   573  var caseWhenSigs = []sig{
   574  	{Arg0: TypeInt},
   575  	{Arg0: TypeReal},
   576  	{Arg0: TypeDecimal},
   577  	{Arg0: TypeString},
   578  	{Arg0: TypeDatetime},
   579  	{Arg0: TypeDuration},
   580  	{Arg0: TypeJSON},
   581  }
   582  
   583  var ifNullSigs = []sig{
   584  	{Arg0: TypeInt},
   585  	{Arg0: TypeReal},
   586  	{Arg0: TypeDecimal},
   587  	{Arg0: TypeString},
   588  	{Arg0: TypeDatetime},
   589  	{Arg0: TypeDuration},
   590  	{Arg0: TypeJSON},
   591  }
   592  
   593  var ifSigs = []sig{
   594  	{Arg0: TypeInt},
   595  	{Arg0: TypeReal},
   596  	{Arg0: TypeDecimal},
   597  	{Arg0: TypeString},
   598  	{Arg0: TypeDatetime},
   599  	{Arg0: TypeDuration},
   600  	{Arg0: TypeJSON},
   601  }
   602  
   603  type sig struct {
   604  	Arg0 TypeContext
   605  }
   606  
   607  type function struct {
   608  	FuncName string
   609  	Sigs     []sig
   610  	Tmpl     *template.Template
   611  }
   612  
   613  var tmplVal = struct {
   614  	Category  string
   615  	Functions []function
   616  }{
   617  	Category: "Control",
   618  	Functions: []function{
   619  		{FuncName: "Case", Sigs: caseWhenSigs, Tmpl: builtinCaseWhenVec},
   620  		{FuncName: "Ifnull", Sigs: ifNullSigs, Tmpl: builtinIfNullVec},
   621  		{FuncName: "If", Sigs: ifSigs, Tmpl: builtinIfVec},
   622  	},
   623  }
   624  
   625  func generateDotGo(fileName string) error {
   626  	w := new(bytes.Buffer)
   627  	w.WriteString(header)
   628  	for _, function := range tmplVal.Functions {
   629  		err := function.Tmpl.InterDircute(w, function)
   630  		if err != nil {
   631  			return err
   632  		}
   633  	}
   634  	data, err := format.Source(w.Bytes())
   635  	if err != nil {
   636  		log.Println("[Warn]", fileName+": gofmt failed", err)
   637  		data = w.Bytes() // write original data for debugging
   638  	}
   639  	return ioutil.WriteFile(fileName, data, 0644)
   640  }
   641  
   642  func generateTestDotGo(fileName string) error {
   643  	w := new(bytes.Buffer)
   644  	err := testFile.InterDircute(w, tmplVal)
   645  	if err != nil {
   646  		return err
   647  	}
   648  	data, err := format.Source(w.Bytes())
   649  	if err != nil {
   650  		log.Println("[Warn]", fileName+": gofmt failed", err)
   651  		data = w.Bytes() // write original data for debugging
   652  	}
   653  	return ioutil.WriteFile(fileName, data, 0644)
   654  }
   655  
   656  // generateOneFile generate one xxx.go file and the associated xxx_test.go file.
   657  func generateOneFile(fileNamePrefix string) (err error) {
   658  
   659  	err = generateDotGo(fileNamePrefix + ".go")
   660  	if err != nil {
   661  		return
   662  	}
   663  	err = generateTestDotGo(fileNamePrefix + "_test.go")
   664  	return
   665  }
   666  
   667  func main() {
   668  	var err error
   669  	outputDir := "."
   670  	err = generateOneFile(filepath.Join(outputDir, "builtin_control_vec_generated"))
   671  	if err != nil {
   672  		log.Fatalln("generateOneFile", err)
   673  	}
   674  }