Skip to content

Commit

Permalink
exec: Add framework for vectorized casts.
Browse files Browse the repository at this point in the history
This PR adds in a framework for performing casts
within the vectorized engine, along with a few
casts implemented already.

Release note: None
  • Loading branch information
rohany committed Aug 7, 2019
1 parent 9990dc7 commit fb1ec8b
Show file tree
Hide file tree
Showing 7 changed files with 426 additions and 1 deletion.
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,7 @@ DOCGEN_TARGETS := bin/.docgen_bnfs bin/.docgen_functions
EXECGEN_TARGETS = \
pkg/sql/exec/any_not_null_agg.eg.go \
pkg/sql/exec/avg_agg.eg.go \
pkg/sql/exec/cast_operator.eg.go \
pkg/sql/exec/coldata/vec.eg.go \
pkg/sql/exec/const.eg.go \
pkg/sql/exec/distinct.eg.go \
Expand Down Expand Up @@ -1459,6 +1460,7 @@ $(SETTINGS_DOC_PAGE): $(settings-doc-gen)

pkg/sql/exec/any_not_null_agg.eg.go: pkg/sql/exec/any_not_null_agg_tmpl.go
pkg/sql/exec/avg_agg.eg.go: pkg/sql/exec/avg_agg_tmpl.go
pkg/sql/exec/cast_operator.eg.go: pkg/sql/exec/cast_operator_tmpl.go
pkg/sql/exec/coldata/vec.eg.go: pkg/sql/exec/coldata/vec_tmpl.go
pkg/sql/exec/const.eg.go: pkg/sql/exec/const_tmpl.go
pkg/sql/exec/distinct.eg.go: pkg/sql/exec/distinct_tmpl.go
Expand Down
12 changes: 12 additions & 0 deletions pkg/sql/distsqlrun/column_exec_setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,18 @@ func planProjectionOperators(
return planProjectionExpr(ctx, t.Operator, t.ResolvedType(), t.TypedLeft(), t.TypedRight(), columnTypes, input)
case *tree.BinaryExpr:
return planProjectionExpr(ctx, t.Operator, t.ResolvedType(), t.TypedLeft(), t.TypedRight(), columnTypes, input)
case *tree.CastExpr:
op, resultIdx, ct, memUsed, err = planProjectionOperators(ctx, t.Expr.(tree.TypedExpr), columnTypes, input)
outputIdx := len(ct)
op, err = exec.GetCastOperator(op, resultIdx, outputIdx, t.Expr.(tree.TypedExpr).ResolvedType(), t.Type)
if err != nil {
return nil, 0, nil, 0, err
}
ct = append(ct, *t.Type)
if sMem, ok := op.(exec.StaticMemoryOperator); ok {
memUsed += sMem.EstimateStaticMemoryUsage()
}
return op, outputIdx, ct, memUsed, err
case *tree.FuncExpr:
var (
inputCols []int
Expand Down
1 change: 1 addition & 0 deletions pkg/sql/exec/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
any_not_null_agg.eg.go
avg_agg.eg.go
cast_operator.eg.go
coldata/vec.eg.go
const.eg.go
distinct.eg.go
Expand Down
153 changes: 153 additions & 0 deletions pkg/sql/exec/cast_operator_tmpl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// Copyright 2019 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

// {{/*
// +build execgen_template
//
// This file is the execgen template for cast_operator.eg.go. It's formatted in a
// special way, so it's both valid Go and a valid text/template input. This
// permits editing this file with editor support.
//
// */}}

package exec

import (
"context"

"github.com/cockroachdb/apd"
"github.com/cockroachdb/cockroach/pkg/sql/exec/types/conv"
"github.com/pkg/errors"

"github.com/cockroachdb/cockroach/pkg/sql/exec/coldata"
"github.com/cockroachdb/cockroach/pkg/sql/exec/types"
semtypes "github.com/cockroachdb/cockroach/pkg/sql/types"
)

// {{/*

type _ALLTYPES interface{}
type _OVERLOADTYPES interface{}
type _TOTYPE interface{}
type _FROMTYPE interface{}

var _ apd.Decimal

//var _ types.T
//var _ bytes.Buffer

func _ASSIGN_CAST(to, from interface{}) {
panic("")
}

// */}}

func GetCastOperator(
input Operator, colIdx int, resultIdx int, fromType *semtypes.T, toType *semtypes.T,
) (Operator, error) {
switch from := conv.FromColumnType(fromType); from {
// {{ range $typ, $overloads := . }}
case types._ALLTYPES:
switch to := conv.FromColumnType(toType); to {
// {{ range $overloads }}
// {{ if isCastFuncSet . }}
case types._OVERLOADTYPES:
return &castOp_FROMTYPE_TOTYPE{
OneInputNode: NewOneInputNode(input),
colIdx: colIdx,
outputIdx: resultIdx,
fromType: from,
toType: to,
}, nil
// {{end}}
// {{end}}
default:
return nil, errors.Errorf("unhandled cast FROM -> TO type: %s -> %s", from, to)
}
// {{end}}
default:
return nil, errors.Errorf("unhandled FROM type: %s", from)
}
}

// {{ range $typ, $overloads := . }}
// {{ range $overloads }}
// {{ if isCastFuncSet . }}

type castOp_FROMTYPE_TOTYPE struct {
OneInputNode
colIdx int
outputIdx int
fromType types.T
toType types.T
}

var _ StaticMemoryOperator = &castOp_FROMTYPE_TOTYPE{}

func (c *castOp_FROMTYPE_TOTYPE) EstimateStaticMemoryUsage() int {
return EstimateBatchSizeBytes([]types.T{c.toType}, coldata.BatchSize)
}

func (c *castOp_FROMTYPE_TOTYPE) Init() {
c.input.Init()
}

func (c *castOp_FROMTYPE_TOTYPE) Next(ctx context.Context) coldata.Batch {
batch := c.input.Next(ctx)
n := batch.Length()
if n == 0 {
return batch
}
if c.outputIdx == batch.Width() {
batch.AppendCol(types._TOTYPE)
}
vec := batch.ColVec(c.colIdx)
col := vec._FROMTYPE()
projVec := batch.ColVec(c.outputIdx)
projCol := projVec._TOTYPE()
if vec.MaybeHasNulls() {
vecNulls := vec.Nulls()
projNulls := projVec.Nulls()
if sel := batch.Selection(); sel != nil {
for _, i := range sel {
if vecNulls.NullAt(uint16(i)) {
projNulls.SetNull(uint16(i))
} else {
_ASSIGN_CAST(projCol[i], col[i])
}
}
} else {
col = col[:n]
projCol = projCol[:n]
for i := range col {
if vecNulls.NullAt(uint16(i)) {
projNulls.SetNull(uint16(i))
} else {
_ASSIGN_CAST(projCol[i], col[i])
}
}
}
} else {
if sel := batch.Selection(); sel != nil {
for _, i := range sel {
_ASSIGN_CAST(projCol[i], col[i])
}
} else {
for i := range col {
_ASSIGN_CAST(projCol[i], col[i])
}
}
}
return batch
}

// {{end}}
// {{end}}
// {{end}}
49 changes: 49 additions & 0 deletions pkg/sql/exec/execgen/cmd/execgen/cast_operator_gen.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2019 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

package main

import (
"io"
"io/ioutil"
"strings"
"text/template"
)

func genCastOperators(wr io.Writer) error {
t, err := ioutil.ReadFile("pkg/sql/exec/cast_operator_tmpl.go")
if err != nil {
return err
}

s := string(t)

assignCast := makeFunctionRegex("_ASSIGN_CAST", 2)
s = assignCast.ReplaceAllString(s, `{{.Assign "$1" "$2"}}`)
s = strings.Replace(s, "_ALLTYPES", "{{$typ}}", -1)
s = strings.Replace(s, "_OVERLOADTYPES", "{{.ToTyp}}", -1)
s = strings.Replace(s, "_FROMTYPE", "{{.FromTyp}}", -1)
s = strings.Replace(s, "_TOTYPE", "{{.ToTyp}}", -1)

isCastFuncSet := func(ov castOverload) bool {
return ov.AssignFunc != nil
}

tmpl, err := template.New("cast_operator").Funcs(template.FuncMap{"isCastFuncSet": isCastFuncSet}).Parse(s)
if err != nil {
return err
}

return tmpl.Execute(wr, castOverloads)
}

func init() {
registerGenerator(genCastOperators, "cast_operator.eg.go")
}
Loading

0 comments on commit fb1ec8b

Please sign in to comment.