// Copyright 2019 PingCAP, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // See the License for the specific language governing permissions and // limitations under the License. //go:build ignore // +build ignore package main import ( "bytes" "flag" "go/format" "io/ioutil" "log" "path/filepath" "text/template" . "github.com/pingcap/tidb/expression/generator/helper" ) const header = `// Copyright 2019 PingCAP, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // See the License for the specific language governing permissions and // limitations under the License. // Code generated by go generate in expression/generator; DO NOT EDIT. package expression ` const newLine = "\n" const builtinStringImports = `import ( "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" ) ` var builtinStringVecTpl = template.Must(template.New("").Parse(` // vecEvalInt evals FIELD(str,str1,str2,str3,...). // See https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_field func (b *builtinField{{ .TypeName }}Sig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error { n := input.NumRows() buf0, err := b.bufAllocator.get(types.ET{{ .ETName }}, n) if err != nil { return err } defer b.bufAllocator.put(buf0) if err := b.args[0].VecEval{{ .TypeName }}(b.ctx, input, buf0); err != nil { return err } buf1, err := b.bufAllocator.get(types.ET{{ .ETName }}, n) if err != nil { return err } defer b.bufAllocator.put(buf1) {{ if .Fixed }} arg0 := buf0.{{ .TypeNameInColumn }}s() {{ end }} result.ResizeInt64(n, false) i64s := result.Int64s() for i := 0; i < n; i++ { i64s[i] = 0 } for i := 1; i < len(b.args); i++ { if err := b.args[i].VecEval{{ .TypeName }}(b.ctx, input, buf1); err != nil { return err } {{ if .Fixed }} arg1 := buf1.{{ .TypeNameInColumn }}s() {{ end }} for j := 0; j < n; j++ { if i64s[j] > 0 || buf0.IsNull(j) || buf1.IsNull(j) { continue } {{ if .Fixed }} if arg0[j] == arg1[j] { {{ else }} {{ if eq .TypeName "String" }} if b.ctor.Compare(buf0.GetString(j), buf1.GetString(j)) == 0 { {{ else }} if buf0.Get{{ .TypeName }}(j) == buf1.Get{{ .TypeName }}(j) { {{ end }} {{ end }} i64s[j] = int64(i) } } } return nil } func (b *builtinField{{ .TypeName }}Sig) vectorized() bool { return true } `)) var builtinStringVecTestTpl = template.Must(template.New("").Parse(` import ( "testing" . "github.com/pingcap/check" "github.com/pingcap/parser/ast" "github.com/pingcap/tidb/types" ) var vecGeneratedBuiltinStringCases = map[string][]vecExprBenchCase{ ast.Field: { {{ range . }} {retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ET{{ .ETName }}, types.ET{{ .ETName }}, types.ET{{ .ETName }}, types.ET{{ .ETName }}}}, {{ end }} }, } func (s *testEvaluatorSuite) TestVectorizedGeneratedBuiltinStringEvalOneVec(c *C) { testVectorizedEvalOneVec(c, vecGeneratedBuiltinStringCases) } func (s *testEvaluatorSuite) TestVectorizedGeneratedBuiltinStringFunc(c *C) { testVectorizedBuiltinFunc(c, vecGeneratedBuiltinStringCases) } func BenchmarkVectorizedGeneratedBuiltinStringEvalOneVec(b *testing.B) { benchmarkVectorizedEvalOneVec(b, vecGeneratedBuiltinStringCases) } func BenchmarkVectorizedGeneratedBuiltinStringFunc(b *testing.B) { benchmarkVectorizedBuiltinFunc(b, vecGeneratedBuiltinStringCases) } `)) var typesMap = []TypeContext{ TypeInt, TypeReal, TypeString, } func generateDotGo(fileName string, types []TypeContext) (err error) { w := new(bytes.Buffer) w.WriteString(header) w.WriteString(newLine) w.WriteString(builtinStringImports) for _, typeCtx := range types { err := builtinStringVecTpl.Execute(w, typeCtx) if err != nil { return err } } data, err := format.Source(w.Bytes()) if err != nil { log.Println("[Warn]", fileName+": gofmt failed", err) data = w.Bytes() // write original data for debugging } return ioutil.WriteFile(fileName, data, 0644) } func generateTestDotGo(fileName string, types []TypeContext) error { w := new(bytes.Buffer) w.WriteString(header) w.WriteString(newLine) err := builtinStringVecTestTpl.Execute(w, types) if err != nil { return err } data, err := format.Source(w.Bytes()) if err != nil { log.Println("[Warn]", fileName+": gofmt failed", err) data = w.Bytes() // write original data for debugging } return ioutil.WriteFile(fileName, data, 0644) } // generateOneFile generate one xxx.go file and the associated xxx_test.go file. func generateOneFile(fileNamePrefix string, types []TypeContext) (err error) { err = generateDotGo(fileNamePrefix+".go", types) if err != nil { return } err = generateTestDotGo(fileNamePrefix+"_test.go", types) return } func main() { flag.Parse() var err error outputDir := "." err = generateOneFile(filepath.Join(outputDir, "builtin_string_vec_generated"), typesMap) if err != nil { log.Fatalln("generateOneFile", err) } }