github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/memex/generator/time_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  var addOrSubTime = template.Must(template.New("").Parse(`
    30  {{ if eq $.FuncName "AddTime" }}
    31  // Copyright 2020 WHTCORPS INC, Inc.
    32  //
    33  // Licensed under the Apache License, Version 2.0 (the "License");
    34  // you may not use this file except in compliance with the License.
    35  // You may obtain a copy of the License at
    36  //
    37  //     http://www.apache.org/licenses/LICENSE-2.0
    38  //
    39  // Unless required by applicable law or agreed to in writing, software
    40  // distributed under the License is distributed on an "AS IS" BASIS,
    41  // See the License for the specific language governing permissions and
    42  // limitations under the License.
    43  
    44  // Code generated by go generate in memex/generator; DO NOT EDIT.
    45  
    46  package memex
    47  
    48  import (
    49  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    50  	"github.com/whtcorpsinc/BerolinaSQL/terror"
    51  	"github.com/whtcorpsinc/milevadb/types"
    52  	"github.com/whtcorpsinc/milevadb/soliton/chunk"
    53  )
    54  {{ end }}
    55  {{ define "SetNull" }}{{if .Output.Fixed}}result.SetNull(i, true){{else}}result.AppendNull(){{end}} // fixed: {{.Output.Fixed }}{{ end }}
    56  {{ define "ConvertStringToDuration" }}
    57  		{{ if and (ne .SigName "builtinAddStringAndStringSig") (ne .SigName "builtinSubStringAndStringSig") }}
    58  		if !isDuration(arg1) {
    59  			{{ template "SetNull" . }}
    60  			continue
    61  		}{{ end }}
    62  		sc := b.ctx.GetStochastikVars().StmtCtx
    63  		arg1Duration, err := types.ParseDuration(sc, arg1, {{if eq .Output.TypeName "String"}}getFsp4TimeAddSub{{else}}types.GetFsp{{end}}(arg1))
    64  		if err != nil {
    65  			if terror.ErrorEqual(err, types.ErrTruncatedWrongVal) {
    66  				sc.AppendWarning(err)
    67  				{{ template "SetNull" . }}
    68  				continue
    69  			}
    70  			return err
    71  		}
    72  {{ end }}
    73  
    74  {{ range .Sigs }}
    75  {{ if .AllNull}}
    76  func (b *{{.SigName}}) vecEval{{ .Output.TypeName }}(input *chunk.Chunk, result *chunk.DeferredCauset) error {
    77  	n := input.NumEvents()
    78  	{{ if .Output.Fixed }}
    79  	result.Resize{{ .Output.TypeNameInDeferredCauset }}(n, true)
    80  	{{ else }}
    81  	result.Reserve{{ .Output.TypeNameInDeferredCauset }}(n)
    82  	for i := 0; i < n; i++ { result.AppendNull() }
    83  	{{ end }}
    84  	return nil
    85  }
    86  {{ else }}
    87  func (b *{{.SigName}}) vecEval{{ .Output.TypeName }}(input *chunk.Chunk, result *chunk.DeferredCauset) error {
    88  	n := input.NumEvents()
    89  {{ $reuse := (and (eq .TypeA.TypeName .Output.TypeName) .TypeA.Fixed) }}
    90  {{ if $reuse }}
    91  	if err := b.args[0].VecEval{{ .TypeA.TypeName }}(b.ctx, input, result); err != nil {
    92  		return err
    93  	}
    94  	buf0 := result
    95  {{ else }}
    96  	buf0, err := b.bufSlabPredictor.get(types.ET{{.TypeA.ETName}}, n)
    97  	if err != nil {
    98  		return err
    99  	}
   100  	defer b.bufSlabPredictor.put(buf0)
   101  	if err := b.args[0].VecEval{{ .TypeA.TypeName }}(b.ctx, input, buf0); err != nil {
   102  		return err
   103  	}
   104  {{ end }}
   105  
   106  {{ if or (eq .SigName "builtinAddStringAndStringSig") (eq .SigName "builtinSubStringAndStringSig") }}
   107  	arg1Type := b.args[1].GetType()
   108  	if allegrosql.HasBinaryFlag(arg1Type.Flag) {
   109  		result.Reserve{{ .Output.TypeNameInDeferredCauset }}(n)
   110  		for i := 0; i < n; i++ {
   111  			result.AppendNull()
   112  		}
   113  		return nil
   114  	}
   115  {{ end }}
   116  
   117  	buf1, err := b.bufSlabPredictor.get(types.ET{{.TypeB.ETName}}, n)
   118  	if err != nil {
   119  		return err
   120  	}
   121  	defer b.bufSlabPredictor.put(buf1)
   122  	if err := b.args[1].VecEval{{ .TypeB.TypeName }}(b.ctx, input, buf1); err != nil {
   123  		return err
   124  	}
   125  
   126  {{ if $reuse }}
   127  	result.MergeNulls(buf1)
   128  {{ else if .Output.Fixed}}
   129  	result.Resize{{ .Output.TypeNameInDeferredCauset }}(n, false)
   130  	result.MergeNulls(buf0, buf1)
   131  {{ else }}
   132  	result.Reserve{{ .Output.TypeNameInDeferredCauset}}(n)
   133  {{ end }}
   134  
   135  {{ if .TypeA.Fixed }}
   136  	arg0s := buf0.{{.TypeA.TypeNameInDeferredCauset}}s()
   137  {{ end }}
   138  {{ if .TypeB.Fixed }}
   139  	arg1s := buf1.{{.TypeB.TypeNameInDeferredCauset}}s()
   140  {{ end }}
   141  {{ if .Output.Fixed }}
   142  	resultSlice := result.{{.Output.TypeNameInDeferredCauset}}s()
   143  {{ end }}
   144  	for i := 0; i < n; i++ {
   145  		{{ if .Output.Fixed }}
   146  		if result.IsNull(i) {
   147  			continue
   148  		}
   149  		{{ else }}
   150  		if buf0.IsNull(i) || buf1.IsNull(i) {
   151  			result.AppendNull()
   152  			continue
   153  		}
   154  		{{ end }}
   155  
   156  		// get arg0 & arg1
   157  		{{ if .TypeA.Fixed }}
   158  		arg0 := arg0s[i]
   159  		{{ else }}
   160  		arg0 := buf0.Get{{ .TypeA.TypeNameInDeferredCauset }}(i)
   161  		{{ end }}
   162  		{{ if .TypeB.Fixed }}
   163  		arg1 := arg1s[i]
   164  		{{ else }}
   165  		arg1 := buf1.Get{{ .TypeB.TypeNameInDeferredCauset }}(i)
   166  		{{ end }}
   167  
   168  		// calculate
   169  	{{ if or (eq .SigName "builtinAddDatetimeAndDurationSig") (eq .SigName "builtinSubDatetimeAndDurationSig") }}
   170  		{{ if eq $.FuncName "AddTime" }}
   171  		output, err := arg0.Add(b.ctx.GetStochastikVars().StmtCtx, types.Duration{Duration: arg1, Fsp: -1})
   172  		{{ else }}
   173  		sc := b.ctx.GetStochastikVars().StmtCtx
   174  		arg1Duration := types.Duration{Duration: arg1, Fsp: -1}
   175  		arg1time, err := arg1Duration.ConvertToTime(sc, allegrosql.TypeDatetime)
   176  		if err != nil {
   177  			return err
   178  		}
   179  		tmFIDeluration := arg0.Sub(sc, &arg1time)
   180  		output, err := tmFIDeluration.ConvertToTime(sc, arg0.Type())
   181  		{{ end }}
   182  		if err != nil {
   183  			return err
   184  		}
   185  		
   186  	{{ else if or (eq .SigName "builtinAddDatetimeAndStringSig") (eq .SigName "builtinSubDatetimeAndStringSig") }}
   187  		{{ if eq $.FuncName "AddTime" }}
   188  		{{ template "ConvertStringToDuration" . }}
   189  		output, err := arg0.Add(sc, arg1Duration)
   190  		{{ else }}
   191  		if !isDuration(arg1) {
   192  			result.SetNull(i, true) // fixed: true
   193  			continue
   194  		}
   195  		sc := b.ctx.GetStochastikVars().StmtCtx
   196  		arg1Duration, err := types.ParseDuration(sc, arg1, types.GetFsp(arg1))
   197  		if err != nil {
   198  			if terror.ErrorEqual(err, types.ErrTruncatedWrongVal) {
   199  				sc.AppendWarning(err)
   200  				result.SetNull(i, true) // fixed: true
   201  				continue
   202  			}
   203  			return err
   204  		}
   205  		arg1time, err := arg1Duration.ConvertToTime(sc, allegrosql.TypeDatetime)
   206  		if err != nil {
   207  			return err
   208  		}
   209  		tmFIDeluration := arg0.Sub(sc, &arg1time)
   210  		output, err := tmFIDeluration.ConvertToTime(sc, allegrosql.TypeDatetime)
   211  		{{ end }}
   212  		if err != nil {
   213  			return err
   214  		}
   215  	{{ else if or (eq .SigName "builtinAddDurationAndDurationSig") (eq .SigName "builtinSubDurationAndDurationSig") }}
   216  		{{ if eq $.FuncName "AddTime" }}
   217  		output, err := types.AddDuration(arg0, arg1)
   218  		if err != nil {
   219  			return err
   220  		}
   221  		{{ else }}
   222  		output, err := types.SubDuration(arg0, arg1)
   223  		if err != nil {
   224  			return err
   225  		}
   226  		{{ end }}
   227  	{{ else if or (eq .SigName "builtinAddDurationAndStringSig") (eq .SigName "builtinSubDurationAndStringSig") }}
   228  		{{ template "ConvertStringToDuration" . }}
   229  		{{ if eq $.FuncName "AddTime" }}
   230  		output, err := types.AddDuration(arg0, arg1Duration.Duration)
   231  		if err != nil {
   232  			return err
   233  		}
   234  		{{ else }}
   235  		output, err := types.SubDuration(arg0, arg1Duration.Duration)
   236  		if err != nil {
   237  			return err
   238  		}
   239  		{{ end }}
   240  	{{ else if or (eq .SigName "builtinAddStringAndDurationSig") (eq .SigName "builtinSubStringAndDurationSig") }}
   241  		sc := b.ctx.GetStochastikVars().StmtCtx
   242  		fsp1 := int8(b.args[1].GetType().Decimal)
   243  		arg1Duration := types.Duration{Duration: arg1, Fsp: fsp1}
   244  		var output string
   245  		if isDuration(arg0) {
   246  			{{ if eq $.FuncName "AddTime" }}
   247  			output, err = strDurationAddDuration(sc, arg0, arg1Duration)
   248  			{{ else }}
   249  			output, err = strDurationSubDuration(sc, arg0, arg1Duration)
   250  			{{ end }}
   251  			if err != nil {
   252  				if terror.ErrorEqual(err, types.ErrTruncatedWrongVal) {
   253  					sc.AppendWarning(err)
   254  					{{ template "SetNull" . }}
   255  					continue
   256  				}
   257  				return err
   258  			}
   259  		} else {
   260  			{{ if eq $.FuncName "AddTime" }}
   261  			output, err = strDatetimeAddDuration(sc, arg0, arg1Duration)
   262  			{{ else }}
   263  			output, err = strDatetimeSubDuration(sc, arg0, arg1Duration)
   264  			{{ end }}
   265  			if err != nil {
   266  				return err
   267  			}
   268  		}
   269  	{{ else if or (eq .SigName "builtinAddStringAndStringSig") (eq .SigName "builtinSubStringAndStringSig") }}
   270  		{{ template "ConvertStringToDuration" . }}
   271  		var output string
   272  		if isDuration(arg0) {
   273  			{{ if eq $.FuncName "AddTime" }}
   274  			output, err = strDurationAddDuration(sc, arg0, arg1Duration)
   275  			{{ else }}
   276  			output, err = strDurationSubDuration(sc, arg0, arg1Duration)
   277  			{{ end }}
   278  			if err != nil {
   279  				if terror.ErrorEqual(err, types.ErrTruncatedWrongVal) {
   280  					sc.AppendWarning(err)
   281  					{{ template "SetNull" . }}
   282  					continue
   283  				}
   284  				return err
   285  			}
   286  		} else {
   287  			{{ if eq $.FuncName "AddTime" }}
   288  			output, err = strDatetimeAddDuration(sc, arg0, arg1Duration)
   289  			{{ else }}
   290  			output, err = strDatetimeSubDuration(sc, arg0, arg1Duration)
   291  			{{ end }}
   292  			if err != nil {
   293  				return err
   294  			}
   295  		}
   296  	{{ else if or (eq .SigName "builtinAddDateAndDurationSig") (eq .SigName "builtinSubDateAndDurationSig") }}
   297  		fsp0 := int8(b.args[0].GetType().Decimal)
   298  		fsp1 := int8(b.args[1].GetType().Decimal)
   299  		arg1Duration := types.Duration{Duration: arg1, Fsp: fsp1}
   300  		{{ if eq $.FuncName "AddTime" }}
   301  		sum, err := types.Duration{Duration: arg0, Fsp: fsp0}.Add(arg1Duration)
   302  		{{ else }}
   303  		sum, err := types.Duration{Duration: arg0, Fsp: fsp0}.Sub(arg1Duration)
   304  		{{ end }}
   305  		if err != nil {
   306  			return err
   307  		}
   308  		output := sum.String()
   309  	{{ else if or (eq .SigName "builtinAddDateAndStringSig") (eq .SigName "builtinSubDateAndStringSig") }}
   310  		{{ template "ConvertStringToDuration" . }}
   311  		fsp0 := int8(b.args[0].GetType().Decimal)
   312  		{{ if eq $.FuncName "AddTime" }}
   313  		sum, err := types.Duration{Duration: arg0, Fsp: fsp0}.Add(arg1Duration)
   314  		{{ else }}
   315  		sum, err := types.Duration{Duration: arg0, Fsp: fsp0}.Sub(arg1Duration)
   316  		{{ end }}
   317  		if err != nil {
   318  			return err
   319  		}
   320  		output := sum.String()
   321  	{{ end }}
   322  
   323  		// commit result
   324  	{{ if .Output.Fixed }}
   325  		resultSlice[i] = output
   326  	{{ else }}
   327  		result.Append{{ .Output.TypeNameInDeferredCauset }}(output)
   328  	{{ end }}
   329  	}
   330  	return nil
   331  }
   332  {{ end }}{{/* if .AllNull */}}
   333  
   334  func (b *{{.SigName}}) vectorized() bool {
   335  	return true
   336  }
   337  {{ end }}{{/* range */}}
   338  `))
   339  
   340  var timeDiff = template.Must(template.New("").Parse(`
   341  {{ define "BufSlabPredictor0" }}
   342  	buf0, err := b.bufSlabPredictor.get(types.ET{{.TypeA.ETName}}, n)
   343  	if err != nil {
   344  		return err
   345  	}
   346  	defer b.bufSlabPredictor.put(buf0)
   347  {{ end }}
   348  {{ define "BufSlabPredictor1" }}
   349  	buf1, err := b.bufSlabPredictor.get(types.ET{{.TypeB.ETName}}, n)
   350  	if err != nil {
   351  		return err
   352  	}
   353  	defer b.bufSlabPredictor.put(buf1)
   354  {{ end }}
   355  {{ define "ArgsVecEval" }}
   356  	if err := b.args[0].VecEval{{ .TypeA.TypeName }}(b.ctx, input, buf0); err != nil {
   357  		return err
   358  	}
   359  	if err := b.args[1].VecEval{{ .TypeB.TypeName }}(b.ctx, input, buf1); err != nil {
   360  		return err
   361  	}
   362  {{ end }}
   363  
   364  {{ range . }}
   365  {{ $AIsString := (eq .TypeA.TypeName "String") }}
   366  {{ $BIsString := (eq .TypeB.TypeName "String") }}
   367  {{ $AIsTime := (eq .TypeA.TypeName "Time") }}
   368  {{ $BIsTime := (eq .TypeB.TypeName "Time") }}
   369  {{ $AIsDuration := (eq .TypeA.TypeName "Duration") }}
   370  {{ $BIsDuration := (eq .TypeB.TypeName "Duration") }}
   371  {{ $MaybeDuration := (or (or $AIsDuration $BIsDuration) (and $AIsString $AIsString)) }}
   372  {{ $reuseA := (eq .TypeA.TypeName "Duration") }}
   373  {{ $reuseB := (eq .TypeB.TypeName "Duration") }}
   374  {{ $reuse  := (or $reuseA $reuseB ) }}
   375  {{ $noNull := (ne .SigName "builtinNullTimeDiffSig") }}
   376  func (b *{{.SigName}}) vecEvalDuration(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   377  	n := input.NumEvents()
   378  	{{- if not $noNull }}
   379  	result.ResizeGoDuration(n, true)
   380  	{{- else }}
   381  		result.ResizeGoDuration(n, false)
   382  		r64s := result.GoDurations()
   383  		{{- if $reuseA }}
   384  			buf0 := result
   385  			{{- template "BufSlabPredictor1" . }}
   386  			{{- template "ArgsVecEval" . }}
   387  			result.MergeNulls(buf1)
   388  		{{- else if $reuseB }}
   389  			buf1 := result
   390  			{{- template "BufSlabPredictor0" . }}
   391  			{{- template "ArgsVecEval" . }}
   392  			result.MergeNulls(buf0)
   393  		{{- else }}
   394  			{{- template "BufSlabPredictor0" . }}
   395  			{{- template "BufSlabPredictor1" . }}
   396  			{{- template "ArgsVecEval" . }}
   397  			result.MergeNulls(buf0, buf1)
   398  		{{- end }}
   399  		{{- if .TypeA.Fixed }}
   400  			arg0 := buf0.{{.TypeA.TypeNameInDeferredCauset}}s()
   401  		{{- end }}
   402  		{{- if .TypeB.Fixed }}
   403  			arg1 := buf1.{{.TypeB.TypeNameInDeferredCauset}}s()
   404  		{{- end }}
   405  
   406  		{{- if (or $AIsDuration $BIsDuration) }}
   407  			var (
   408  				lhs    types.Duration
   409  				rhs    types.Duration
   410  			)
   411  		{{- end }}
   412  		{{- if or (or $AIsString $BIsString) (and $AIsTime $BIsTime) }}
   413  			stmtCtx := b.ctx.GetStochastikVars().StmtCtx
   414  		{{- end }}
   415  	for i:=0; i<n ; i++{
   416  		if result.IsNull(i) {
   417  			continue
   418  		}
   419  
   420  		{{- if $AIsString }}
   421  			{{ if $BIsDuration }} lhsDur, _, lhsIsDuration,
   422  			{{- else if $BIsTime }} _, lhsTime, lhsIsDuration,
   423  			{{- else if $BIsString }} lhsDur, lhsTime, lhsIsDuration,
   424  			{{- end }}  err := convertStringToDuration(stmtCtx, buf0.GetString(i), int8(b.tp.Decimal))
   425  			if err != nil  {
   426  				return err
   427  			}
   428  			{{- if $BIsDuration }}
   429  			if !lhsIsDuration {
   430  				result.SetNull(i, true)
   431  				continue
   432  			}
   433  			lhs = lhsDur
   434  			{{- else if $BIsTime }}
   435  			if lhsIsDuration {
   436  				result.SetNull(i, true)
   437  				continue
   438  			}
   439  			{{- end }}
   440  		{{- else if $AIsTime }}
   441  			lhsTime := arg0[i]
   442  		{{- else }}
   443  			lhs.Duration = arg0[i]
   444  		{{- end }}
   445  
   446  		{{- if $BIsString }}
   447  			{{ if $AIsDuration }} rhsDur, _, rhsIsDuration,
   448  			{{- else if $AIsTime }}_, rhsTime, rhsIsDuration,
   449  			{{- else if $AIsString }} rhsDur, rhsTime, rhsIsDuration,
   450  			{{- end}}  err := convertStringToDuration(stmtCtx, buf1.GetString(i), int8(b.tp.Decimal))
   451  			if err != nil  {
   452  				return err
   453  			}
   454  			{{- if $AIsDuration }}
   455  			if !rhsIsDuration {
   456  				result.SetNull(i, true)
   457  				continue
   458  			}
   459  			rhs = rhsDur
   460  			{{- else if $AIsTime }}
   461  			if rhsIsDuration {
   462  				result.SetNull(i, true)
   463  				continue
   464  			}
   465  			{{- end }}
   466  		{{- else if $BIsTime }}
   467  			rhsTime := arg1[i]
   468  		{{- else }}
   469  			rhs.Duration = arg1[i]
   470  		{{- end }}
   471  
   472  		{{- if and $AIsString $BIsString }}
   473  			if lhsIsDuration != rhsIsDuration {
   474  				result.SetNull(i, true)
   475  				continue
   476  			}
   477  			var (
   478  				d types.Duration
   479  				isNull bool
   480  			)
   481  			if lhsIsDuration {
   482  				d, isNull, err = calculateDurationTimeDiff(b.ctx, lhsDur, rhsDur)
   483  			} else {
   484  				d, isNull, err = calculateTimeDiff(stmtCtx, lhsTime, rhsTime)
   485  			}
   486  		{{- else if or $AIsDuration $BIsDuration }}
   487  			d, isNull, err := calculateDurationTimeDiff(b.ctx, lhs, rhs)
   488  		{{- else if or $AIsTime $BIsTime }}
   489  			d, isNull, err := calculateTimeDiff(stmtCtx, lhsTime, rhsTime)
   490  		{{- end }}
   491  		if err != nil {
   492  			return err
   493  		}
   494  		if isNull {
   495  			result.SetNull(i, true)
   496  			continue
   497  		}
   498  		r64s[i] = d.Duration
   499  	}
   500  	{{- end }} {{/* if $noNull */}}
   501  	return nil
   502  }
   503  
   504  func (b *{{.SigName}}) vectorized() bool {
   505  	return true
   506  }
   507  {{ end }}{{/* range */}}
   508  `))
   509  
   510  var addOrSubDate = template.Must(template.New("").Parse(`
   511  {{ range .Sigs }}
   512  {{- if eq .TypeA.TypeName "Duration" }}
   513  func (b *{{.SigName}}) vecEvalDuration(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   514  {{- else }}
   515  func (b *{{.SigName}}) vecEvalTime(input *chunk.Chunk, result *chunk.DeferredCauset) error {
   516  {{- end }}
   517  	n := input.NumEvents()
   518  	unit, isNull, err := b.args[2].EvalString(b.ctx, chunk.Event{})
   519  	if err != nil {
   520  		return err
   521  	}
   522  	if isNull {
   523  		{{- if eq .TypeA.TypeName "Duration" }}
   524  			result.ResizeGoDuration(n, true)
   525  		{{- else }}
   526  			result.ResizeTime(n, true)
   527  		{{- end }}
   528  		return nil
   529  	}
   530  
   531  	intervalBuf, err := b.bufSlabPredictor.get(types.ETString, n)
   532  	if err != nil {
   533  		return err
   534  	}
   535  	defer b.bufSlabPredictor.put(intervalBuf)
   536  	if err := b.vecGetIntervalFrom{{.TypeB.ETName}}(&b.baseBuiltinFunc, input, unit, intervalBuf); err != nil {
   537  		return err
   538  	}
   539  
   540  	{{ if eq .TypeA.TypeName "Duration" }}
   541  		result.ResizeGoDuration(n, false)
   542  		if err := b.args[0].VecEvalDuration(b.ctx, input, result); err != nil {
   543  			return err
   544  		}
   545  
   546  		result.MergeNulls(intervalBuf)
   547  		resDurations := result.GoDurations()
   548  		iterDuration := types.Duration{Fsp: types.MaxFsp}
   549  	{{ else }}
   550  		if err := b.vecGetDateFrom{{.TypeA.ETName}}(&b.baseBuiltinFunc, input, unit, result); err != nil {
   551  			return err
   552  		}
   553  
   554  		result.MergeNulls(intervalBuf)
   555  		resDates := result.Times()
   556  	{{ end -}}
   557  
   558  	for i := 0; i < n; i++ {
   559  		if result.IsNull(i) {
   560  			continue
   561  		}
   562  
   563  		{{- if eq .TypeA.TypeName "Duration" }}
   564  			iterDuration.Duration = resDurations[i]
   565  			{{- if eq $.FuncName "AddDate" }}
   566  				resDuration, isNull, err := b.addDuration(b.ctx, iterDuration, intervalBuf.GetString(i), unit)
   567  			{{- else }}
   568  				resDuration, isNull, err := b.subDuration(b.ctx, iterDuration, intervalBuf.GetString(i), unit)
   569  			{{- end }}
   570  		{{- else }}
   571  			{{- if eq $.FuncName "AddDate" }}
   572  				resDate, isNull, err := b.add(b.ctx, resDates[i], intervalBuf.GetString(i), unit)
   573  			{{- else }}
   574  				resDate, isNull, err := b.sub(b.ctx, resDates[i], intervalBuf.GetString(i), unit)
   575  			{{- end }}
   576  		{{- end }}
   577  		if err != nil {
   578  			return err
   579  		}
   580  		if isNull {
   581  			result.SetNull(i, true)
   582  		} else {
   583  			{{- if eq .TypeA.TypeName "Duration" }}
   584  				resDurations[i] = resDuration.Duration
   585  			{{- else }}
   586  				resDates[i] = resDate
   587  			{{- end }}
   588  		}
   589  	}
   590  	return nil
   591  }
   592  
   593  func (b *{{.SigName}}) vectorized() bool {
   594  	return true
   595  }
   596  {{ end }}{{/* range */}}
   597  `))
   598  
   599  var testFileFuncs = template.FuncMap{
   600  	"getIntervalUnitList": func() []string {
   601  		return []string{
   602  			"MICROSECOND",
   603  			"SECOND",
   604  			"MINUTE",
   605  			"HOUR",
   606  			"DAY",
   607  			"WEEK",
   608  			"MONTH",
   609  			"QUARTER",
   610  			"YEAR",
   611  			"SECOND_MICROSECOND",
   612  			"MINUTE_MICROSECOND",
   613  			"MINUTE_SECOND",
   614  			"HOUR_MICROSECOND",
   615  			"HOUR_SECOND",
   616  			"HOUR_MINUTE",
   617  			"DAY_MICROSECOND",
   618  			"DAY_SECOND",
   619  			"DAY_MINUTE",
   620  			"DAY_HOUR",
   621  			"YEAR_MONTH",
   622  		}
   623  	},
   624  }
   625  
   626  var testFile = template.Must(template.New("").Funcs(testFileFuncs).Parse(`
   627  // Copyright 2020 WHTCORPS INC, Inc.
   628  //
   629  // Licensed under the Apache License, Version 2.0 (the "License");
   630  // you may not use this file except in compliance with the License.
   631  // You may obtain a copy of the License at
   632  //
   633  //     http://www.apache.org/licenses/LICENSE-2.0
   634  //
   635  // Unless required by applicable law or agreed to in writing, software
   636  // distributed under the License is distributed on an "AS IS" BASIS,
   637  // See the License for the specific language governing permissions and
   638  // limitations under the License.
   639  
   640  // Code generated by go generate in memex/generator; DO NOT EDIT.
   641  
   642  package memex
   643  
   644  import (
   645  	"math"
   646  	"testing"
   647  
   648  	. "github.com/whtcorpsinc/check"
   649  	"github.com/whtcorpsinc/BerolinaSQL/ast"
   650  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
   651  	"github.com/whtcorpsinc/milevadb/types"
   652  )
   653  
   654  type gener struct {
   655  	defaultGener
   656  }
   657  
   658  func (g gener) gen() interface{} {
   659  	result := g.defaultGener.gen()
   660  	if _, ok := result.(string); ok {
   661  		dg := newDefaultGener(0, types.ETDuration)
   662  		d := dg.gen().(types.Duration)
   663  		if int8(d.Duration)%2 == 0 {
   664  			d.Fsp = 0
   665  		} else {
   666  			d.Fsp = 1
   667  		}
   668  		result = d.String()
   669  	}
   670  	return result
   671  }
   672  
   673  {{ define "addOrSubDateCases" }}
   674  	{{- $unitList := getIntervalUnitList -}}
   675  	{{- range $sig := .Sigs }}
   676  		// {{ $sig.SigName }}
   677  		{{- range $unit := $unitList }}
   678  			{
   679  				retEvalType: types.ET{{ $sig.Output.ETName }},
   680  				childrenTypes: []types.EvalType{types.ET{{ $sig.TypeA.ETName }}, types.ET{{ $sig.TypeB.ETName }}, types.ETString},
   681  				geners: []dataGenerator{
   682  					{{- if eq $sig.TypeA.ETName "String"}}
   683  						&dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()},
   684  					{{- else if eq $sig.TypeA.ETName "Int"}}
   685  						&dateTimeIntGener{dateTimeGener: dateTimeGener{randGen: newDefaultRandGen()}, nullRation: 0.2},
   686  					{{- else }}
   687  						newDefaultGener(0.2, types.ET{{$sig.TypeA.ETName}}),
   688  					{{- end }}
   689  
   690  					{{- if eq $sig.TypeB.ETName "String" }}
   691  						&numStrGener{rangeInt64Gener{math.MinInt32 + 1, math.MaxInt32, newDefaultRandGen()}},
   692  					{{- else }}
   693  						newDefaultGener(0.2, types.ET{{$sig.TypeB.ETName}}),
   694  					{{- end }}
   695  				},
   696  				constants: []*Constant{nil, nil, {Value: types.NewStringCauset("{{$unit}}"), RetType: types.NewFieldType(allegrosql.TypeString)}},
   697  				chunkSize: 128,
   698  			},
   699  		{{- end }}
   700  	{{- end }}
   701  {{ end }}
   702  
   703  {{ define "addOrSubTimeCases" }}
   704  	{{- range $sig := .Sigs }}
   705  		// {{ $sig.SigName }}
   706  			{
   707  				retEvalType: types.ET{{ .Output.ETName }},
   708  				{{- if eq .TestTypeA "" }}
   709  				childrenTypes: []types.EvalType{types.ET{{ .TypeA.ETName }}, types.ET{{ .TypeB.ETName }}},
   710  				{{- else }}
   711  				childrenTypes: []types.EvalType{types.ET{{ .TestTypeA }}, types.ET{{ .TestTypeB }}},
   712  				{{- end }}
   713  				{{- if ne .FieldTypeA "" }}
   714  				childrenFieldTypes: []*types.FieldType{types.NewFieldType(allegrosql.Type{{.FieldTypeA}}), types.NewFieldType(allegrosql.Type{{.FieldTypeB}})},
   715  				{{- end }}
   716  				geners: []dataGenerator{
   717  					{{- if eq .TestTypeA "" }}
   718  					gener{*newDefaultGener(0.2, types.ET{{.TypeA.ETName}})},
   719  					gener{*newDefaultGener(0.2, types.ET{{.TypeB.ETName}})},
   720  					{{- else }}
   721  					gener{*newDefaultGener(0.2, types.ET{{ .TestTypeA }})},
   722  					gener{*newDefaultGener(0.2, types.ET{{ .TestTypeB }})},
   723  					{{- end }}
   724  				},
   725  			},
   726  	{{- end }}
   727  {{ end }}
   728  
   729  {{/* Add more test cases here if we have more functions in this file */}}
   730  var vecBuiltin{{.Category}}GeneratedCases = map[string][]vecExprBenchCase{
   731  {{- range .Functions }}
   732  	{{- if eq .FuncName "AddTime" }}
   733  		ast.AddTime: {
   734  			{{- template "addOrSubTimeCases" . -}}
   735  		},
   736  	{{ end }}
   737  	{{- if eq .FuncName "SubTime" }}
   738  		ast.SubTime: {
   739  			{{- template "addOrSubTimeCases" . -}}
   740  		},
   741  	{{ end }}
   742  	{{- if eq .FuncName "TimeDiff" }}
   743  		ast.TimeDiff: {
   744  			// builtinNullTimeDiffSig
   745  			{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETDuration, types.ETDatetime}},
   746  			{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETDuration, types.ETTimestamp}},
   747  			{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETDatetime, types.ETDuration}},
   748  			{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETTimestamp, types.ETDuration}},
   749  			// builtinDurationDurationTimeDiffSig
   750  			{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETDuration, types.ETDuration}},
   751  			// builtinDurationStringTimeDiffSig
   752  			{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETDuration, types.ETString}, geners: []dataGenerator{nil, &dateTimeStrGener{Year: 2020, Month: 11, randGen: newDefaultRandGen()}}},
   753  			{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETDuration, types.ETString}, geners: []dataGenerator{nil, &dateTimeStrGener{Year: 2020, Month: 10, randGen: newDefaultRandGen()}}},
   754  			{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETDuration, types.ETString}, geners: []dataGenerator{nil, &dateTimeStrGener{Year: 2020, Month: 10, Fsp: 4, randGen: newDefaultRandGen()}}},
   755  			// builtinTimeTimeTimeDiffSig
   756  			{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETDatetime, types.ETDatetime}, geners: []dataGenerator{&dateTimeGener{Year: 2020, Month: 10, randGen: newDefaultRandGen()}, &dateTimeGener{Year: 2020, Month: 10, randGen: newDefaultRandGen()}}},
   757  			{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETDatetime, types.ETTimestamp}, geners: []dataGenerator{&dateTimeGener{Year: 2020, Month: 10, randGen: newDefaultRandGen()}, &dateTimeGener{Year: 2020, Month: 10, randGen: newDefaultRandGen()}}},
   758  			{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETTimestamp, types.ETTimestamp}, geners: []dataGenerator{&dateTimeGener{Year: 2020, Month: 10, randGen: newDefaultRandGen()}, &dateTimeGener{Year: 2020, Month: 10, randGen: newDefaultRandGen()}}},
   759  			{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETTimestamp, types.ETDatetime}, geners: []dataGenerator{&dateTimeGener{Year: 2020, Month: 10, randGen: newDefaultRandGen()}, &dateTimeGener{Year: 2020, Month: 10, randGen: newDefaultRandGen()}}},
   760  			// builtinTimeStringTimeDiffSig
   761  			{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETDatetime, types.ETString}, geners: []dataGenerator{&dateTimeGener{Year: 2020, Month: 10, randGen: newDefaultRandGen()}, &dateTimeStrGener{Year: 2020, Month: 10, randGen: newDefaultRandGen()}}},
   762  			{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETTimestamp, types.ETString}, geners: []dataGenerator{&dateTimeGener{Year: 2020, Month: 10, randGen: newDefaultRandGen()}, &dateTimeStrGener{Year: 2020, Month: 10, randGen: newDefaultRandGen()}}},
   763  			// builtinStringDurationTimeDiffSig
   764  			{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETString, types.ETDuration}, geners: []dataGenerator{&dateTimeStrGener{Year: 2020, Month: 10, randGen: newDefaultRandGen()}, nil}},
   765  			// builtinStringTimeTimeDiffSig
   766  			{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETString, types.ETDatetime}, geners: []dataGenerator{&dateTimeStrGener{Year: 2020, Month: 10, randGen: newDefaultRandGen()}, &dateTimeGener{Year: 2020, Month: 10, randGen: newDefaultRandGen()}}},
   767  			{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETString, types.ETTimestamp}, geners: []dataGenerator{&dateTimeStrGener{Year: 2020, Month: 10, randGen: newDefaultRandGen()}, &dateTimeGener{Year: 2020, Month: 10, randGen: newDefaultRandGen()}}},
   768  			// builtinStringStringTimeDiffSig
   769  			{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETString, types.ETString}, geners: []dataGenerator{&dateTimeStrGener{Year: 2020, Month: 10, randGen: newDefaultRandGen()}, &dateTimeStrGener{Year: 2020, Month: 10, randGen: newDefaultRandGen()}}},
   770  		},
   771  	{{ end }}
   772  	{{- if eq .FuncName "AddDate" }}
   773  		ast.AddDate: {
   774  			{{- template "addOrSubDateCases" . -}}
   775  		},
   776  	{{ end }}
   777  	{{- if eq .FuncName "SubDate" }}
   778  		ast.SubDate: {
   779  			{{- template "addOrSubDateCases" . -}}
   780  		},
   781  	{{ end }}
   782  {{ end }}
   783  }
   784  
   785  func (s *testVectorizeSuite1) TestVectorizedBuiltin{{.Category}}EvalOneVecGenerated(c *C) {
   786  	testVectorizedEvalOneVec(c, vecBuiltin{{.Category}}GeneratedCases)
   787  }
   788  
   789  func (s *testVectorizeSuite1) TestVectorizedBuiltin{{.Category}}FuncGenerated(c *C) {
   790  	testVectorizedBuiltinFunc(c, vecBuiltin{{.Category}}GeneratedCases)
   791  }
   792  
   793  func BenchmarkVectorizedBuiltin{{.Category}}EvalOneVecGenerated(b *testing.B) {
   794  	benchmarkVectorizedEvalOneVec(b, vecBuiltin{{.Category}}GeneratedCases)
   795  }
   796  
   797  func BenchmarkVectorizedBuiltin{{.Category}}FuncGenerated(b *testing.B) {
   798  	benchmarkVectorizedBuiltinFunc(b, vecBuiltin{{.Category}}GeneratedCases)
   799  }
   800  `))
   801  
   802  var addTimeSigsTmpl = []sig{
   803  	{SigName: "builtinAddDatetimeAndDurationSig", TypeA: TypeDatetime, TypeB: TypeDuration, Output: TypeDatetime},
   804  	{SigName: "builtinAddDatetimeAndStringSig", TypeA: TypeDatetime, TypeB: TypeString, Output: TypeDatetime},
   805  	{SigName: "builtinAddDurationAndDurationSig", TypeA: TypeDuration, TypeB: TypeDuration, Output: TypeDuration},
   806  	{SigName: "builtinAddDurationAndStringSig", TypeA: TypeDuration, TypeB: TypeString, Output: TypeDuration},
   807  	{SigName: "builtinAddStringAndDurationSig", TypeA: TypeString, TypeB: TypeDuration, Output: TypeString},
   808  	{SigName: "builtinAddStringAndStringSig", TypeA: TypeString, TypeB: TypeString, Output: TypeString},
   809  	{SigName: "builtinAddDateAndDurationSig", TypeA: TypeDuration, TypeB: TypeDuration, Output: TypeString, FieldTypeA: "Date", FieldTypeB: "Duration", TestTypeA: "Datetime", TestTypeB: "Duration"},
   810  	{SigName: "builtinAddDateAndStringSig", TypeA: TypeDuration, TypeB: TypeString, Output: TypeString, FieldTypeA: "Date", FieldTypeB: "String", TestTypeA: "Datetime", TestTypeB: "String"},
   811  
   812  	{SigName: "builtinAddTimeDateTimeNullSig", TypeA: TypeDatetime, TypeB: TypeDatetime, Output: TypeDatetime, AllNull: true},
   813  	{SigName: "builtinAddTimeStringNullSig", TypeA: TypeDatetime, TypeB: TypeDatetime, Output: TypeString, AllNull: true, FieldTypeA: "Date", FieldTypeB: "Datetime"},
   814  	{SigName: "builtinAddTimeDurationNullSig", TypeA: TypeDuration, TypeB: TypeDatetime, Output: TypeDuration, AllNull: true},
   815  }
   816  
   817  var subTimeSigsTmpl = []sig{
   818  	{SigName: "builtinSubDatetimeAndDurationSig", TypeA: TypeDatetime, TypeB: TypeDuration, Output: TypeDatetime},
   819  	{SigName: "builtinSubDatetimeAndStringSig", TypeA: TypeDatetime, TypeB: TypeString, Output: TypeDatetime},
   820  	{SigName: "builtinSubDurationAndDurationSig", TypeA: TypeDuration, TypeB: TypeDuration, Output: TypeDuration},
   821  	{SigName: "builtinSubDurationAndStringSig", TypeA: TypeDuration, TypeB: TypeString, Output: TypeDuration},
   822  	{SigName: "builtinSubStringAndDurationSig", TypeA: TypeString, TypeB: TypeDuration, Output: TypeString},
   823  	{SigName: "builtinSubStringAndStringSig", TypeA: TypeString, TypeB: TypeString, Output: TypeString},
   824  	{SigName: "builtinSubDateAndDurationSig", TypeA: TypeDuration, TypeB: TypeDuration, Output: TypeString, FieldTypeA: "Date", FieldTypeB: "Duration", TestTypeA: "Datetime", TestTypeB: "Duration"},
   825  	{SigName: "builtinSubDateAndStringSig", TypeA: TypeDuration, TypeB: TypeString, Output: TypeString, FieldTypeA: "Date", FieldTypeB: "String", TestTypeA: "Datetime", TestTypeB: "String"},
   826  
   827  	{SigName: "builtinSubTimeDateTimeNullSig", TypeA: TypeDatetime, TypeB: TypeDatetime, Output: TypeDatetime, AllNull: true},
   828  	{SigName: "builtinSubTimeStringNullSig", TypeA: TypeDatetime, TypeB: TypeDatetime, Output: TypeString, AllNull: true, FieldTypeA: "Date", FieldTypeB: "Datetime"},
   829  	{SigName: "builtinSubTimeDurationNullSig", TypeA: TypeDuration, TypeB: TypeDatetime, Output: TypeDuration, AllNull: true},
   830  }
   831  
   832  var timeDiffSigsTmpl = []sig{
   833  	{SigName: "builtinNullTimeDiffSig", Output: TypeDuration},
   834  	{SigName: "builtinTimeStringTimeDiffSig", TypeA: TypeDatetime, TypeB: TypeString, Output: TypeDuration},
   835  	{SigName: "builtinDurationStringTimeDiffSig", TypeA: TypeDuration, TypeB: TypeString, Output: TypeDuration},
   836  	{SigName: "builtinDurationDurationTimeDiffSig", TypeA: TypeDuration, TypeB: TypeDuration, Output: TypeDuration},
   837  	{SigName: "builtinStringTimeTimeDiffSig", TypeA: TypeString, TypeB: TypeDatetime, Output: TypeDuration},
   838  	{SigName: "builtinStringDurationTimeDiffSig", TypeA: TypeString, TypeB: TypeDuration, Output: TypeDuration},
   839  	{SigName: "builtinStringStringTimeDiffSig", TypeA: TypeString, TypeB: TypeString, Output: TypeDuration},
   840  	{SigName: "builtinTimeTimeTimeDiffSig", TypeA: TypeDatetime, TypeB: TypeDatetime, Output: TypeDuration},
   841  }
   842  
   843  var addDataSigsTmpl = []sig{
   844  	{SigName: "builtinAddDateStringStringSig", TypeA: TypeString, TypeB: TypeString, Output: TypeDatetime},
   845  	{SigName: "builtinAddDateStringIntSig", TypeA: TypeString, TypeB: TypeInt, Output: TypeDatetime},
   846  	{SigName: "builtinAddDateStringRealSig", TypeA: TypeString, TypeB: TypeReal, Output: TypeDatetime},
   847  	{SigName: "builtinAddDateStringDecimalSig", TypeA: TypeString, TypeB: TypeDecimal, Output: TypeDatetime},
   848  	{SigName: "builtinAddDateIntStringSig", TypeA: TypeInt, TypeB: TypeString, Output: TypeDatetime},
   849  	{SigName: "builtinAddDateIntIntSig", TypeA: TypeInt, TypeB: TypeInt, Output: TypeDatetime},
   850  	{SigName: "builtinAddDateIntRealSig", TypeA: TypeInt, TypeB: TypeReal, Output: TypeDatetime},
   851  	{SigName: "builtinAddDateIntDecimalSig", TypeA: TypeInt, TypeB: TypeDecimal, Output: TypeDatetime},
   852  	{SigName: "builtinAddDateDatetimeStringSig", TypeA: TypeDatetime, TypeB: TypeString, Output: TypeDatetime},
   853  	{SigName: "builtinAddDateDatetimeIntSig", TypeA: TypeDatetime, TypeB: TypeInt, Output: TypeDatetime},
   854  	{SigName: "builtinAddDateDatetimeRealSig", TypeA: TypeDatetime, TypeB: TypeReal, Output: TypeDatetime},
   855  	{SigName: "builtinAddDateDatetimeDecimalSig", TypeA: TypeDatetime, TypeB: TypeDecimal, Output: TypeDatetime},
   856  	{SigName: "builtinAddDateDurationStringSig", TypeA: TypeDuration, TypeB: TypeString, Output: TypeDuration},
   857  	{SigName: "builtinAddDateDurationIntSig", TypeA: TypeDuration, TypeB: TypeInt, Output: TypeDuration},
   858  	{SigName: "builtinAddDateDurationRealSig", TypeA: TypeDuration, TypeB: TypeReal, Output: TypeDuration},
   859  	{SigName: "builtinAddDateDurationDecimalSig", TypeA: TypeDuration, TypeB: TypeDecimal, Output: TypeDuration},
   860  }
   861  
   862  var subDataSigsTmpl = []sig{
   863  	{SigName: "builtinSubDateStringStringSig", TypeA: TypeString, TypeB: TypeString, Output: TypeDatetime},
   864  	{SigName: "builtinSubDateStringIntSig", TypeA: TypeString, TypeB: TypeInt, Output: TypeDatetime},
   865  	{SigName: "builtinSubDateStringRealSig", TypeA: TypeString, TypeB: TypeReal, Output: TypeDatetime},
   866  	{SigName: "builtinSubDateStringDecimalSig", TypeA: TypeString, TypeB: TypeDecimal, Output: TypeDatetime},
   867  	{SigName: "builtinSubDateIntStringSig", TypeA: TypeInt, TypeB: TypeString, Output: TypeDatetime},
   868  	{SigName: "builtinSubDateIntIntSig", TypeA: TypeInt, TypeB: TypeInt, Output: TypeDatetime},
   869  	{SigName: "builtinSubDateIntRealSig", TypeA: TypeInt, TypeB: TypeReal, Output: TypeDatetime},
   870  	{SigName: "builtinSubDateIntDecimalSig", TypeA: TypeInt, TypeB: TypeDecimal, Output: TypeDatetime},
   871  	{SigName: "builtinSubDateDatetimeStringSig", TypeA: TypeDatetime, TypeB: TypeString, Output: TypeDatetime},
   872  	{SigName: "builtinSubDateDatetimeIntSig", TypeA: TypeDatetime, TypeB: TypeInt, Output: TypeDatetime},
   873  	{SigName: "builtinSubDateDatetimeRealSig", TypeA: TypeDatetime, TypeB: TypeReal, Output: TypeDatetime},
   874  	{SigName: "builtinSubDateDatetimeDecimalSig", TypeA: TypeDatetime, TypeB: TypeDecimal, Output: TypeDatetime},
   875  	{SigName: "builtinSubDateDurationStringSig", TypeA: TypeDuration, TypeB: TypeString, Output: TypeDuration},
   876  	{SigName: "builtinSubDateDurationIntSig", TypeA: TypeDuration, TypeB: TypeInt, Output: TypeDuration},
   877  	{SigName: "builtinSubDateDurationRealSig", TypeA: TypeDuration, TypeB: TypeReal, Output: TypeDuration},
   878  	{SigName: "builtinSubDateDurationDecimalSig", TypeA: TypeDuration, TypeB: TypeDecimal, Output: TypeDuration},
   879  }
   880  
   881  type sig struct {
   882  	SigName                string
   883  	TypeA, TypeB, Output   TypeContext
   884  	FieldTypeA, FieldTypeB string // Optional
   885  	TestTypeA, TestTypeB   string // Optional, specific Type for test in builtinAddDateAndDurationSig & builtinAddDateAndStringSig
   886  	AllNull                bool
   887  }
   888  
   889  type function struct {
   890  	FuncName string
   891  	Sigs     []sig
   892  }
   893  
   894  var tmplVal = struct {
   895  	Category  string
   896  	Functions []function
   897  }{
   898  	Category: "Time",
   899  	Functions: []function{
   900  		{FuncName: "AddTime", Sigs: addTimeSigsTmpl},
   901  		{FuncName: "SubTime", Sigs: subTimeSigsTmpl},
   902  		{FuncName: "TimeDiff", Sigs: timeDiffSigsTmpl},
   903  		{FuncName: "AddDate", Sigs: addDataSigsTmpl},
   904  		{FuncName: "SubDate", Sigs: subDataSigsTmpl},
   905  	},
   906  }
   907  
   908  func generateDotGo(fileName string) error {
   909  	w := new(bytes.Buffer)
   910  	err := addOrSubTime.InterDircute(w, function{FuncName: "AddTime", Sigs: addTimeSigsTmpl})
   911  	if err != nil {
   912  		return err
   913  	}
   914  	err = addOrSubTime.InterDircute(w, function{FuncName: "SubTime", Sigs: subTimeSigsTmpl})
   915  	if err != nil {
   916  		return err
   917  	}
   918  	err = timeDiff.InterDircute(w, timeDiffSigsTmpl)
   919  	if err != nil {
   920  		return err
   921  	}
   922  	err = addOrSubDate.InterDircute(w, function{FuncName: "AddDate", Sigs: addDataSigsTmpl})
   923  	if err != nil {
   924  		return err
   925  	}
   926  	err = addOrSubDate.InterDircute(w, function{FuncName: "SubDate", Sigs: subDataSigsTmpl})
   927  	if err != nil {
   928  		return err
   929  	}
   930  	data, err := format.Source(w.Bytes())
   931  	if err != nil {
   932  		log.Println("[Warn]", fileName+": gofmt failed", err)
   933  		data = w.Bytes() // write original data for debugging
   934  	}
   935  	return ioutil.WriteFile(fileName, data, 0644)
   936  }
   937  
   938  func generateTestDotGo(fileName string) error {
   939  	w := new(bytes.Buffer)
   940  	err := testFile.InterDircute(w, tmplVal)
   941  	if err != nil {
   942  		return err
   943  	}
   944  	data, err := format.Source(w.Bytes())
   945  	if err != nil {
   946  		log.Println("[Warn]", fileName+": gofmt failed", err)
   947  		data = w.Bytes() // write original data for debugging
   948  	}
   949  	return ioutil.WriteFile(fileName, data, 0644)
   950  }
   951  
   952  // generateOneFile generate one xxx.go file and the associated xxx_test.go file.
   953  func generateOneFile(fileNamePrefix string) (err error) {
   954  
   955  	err = generateDotGo(fileNamePrefix + ".go")
   956  	if err != nil {
   957  		return
   958  	}
   959  	err = generateTestDotGo(fileNamePrefix + "_test.go")
   960  	return
   961  }
   962  
   963  func main() {
   964  	var err error
   965  	outputDir := "."
   966  	err = generateOneFile(filepath.Join(outputDir, "builtin_time_vec_generated"))
   967  	if err != nil {
   968  		log.Fatalln("generateOneFile", err)
   969  	}
   970  }