From a62c02a033fc1bf880bdc685f8230f9d07b944a4 Mon Sep 17 00:00:00 2001 From: Arun Ranganathan Date: Sat, 13 Jun 2020 23:07:58 -0400 Subject: [PATCH] colexec: add support for Pow binary operator This commit resolves: #49465 Previously, there was no support for Pow (**) in vectorized engine. This commit adds Pow operator. I added Pow to binaryOpMethods and registered inputs/outputs for this operator. Release note (sql change): Vectorized engine now support Pow operator. --- .../execgen/cmd/execgen/overloads_bin.go | 48 ++++++++++++++++++- .../colexec/execgen/supported_bin_cmp_ops.go | 1 + .../testdata/logic_test/vectorize_overloads | 45 +++++++++++++++++ 3 files changed, 92 insertions(+), 2 deletions(-) diff --git a/pkg/sql/colexec/execgen/cmd/execgen/overloads_bin.go b/pkg/sql/colexec/execgen/cmd/execgen/overloads_bin.go index d94378b98273..9d8a2805bbe5 100644 --- a/pkg/sql/colexec/execgen/cmd/execgen/overloads_bin.go +++ b/pkg/sql/colexec/execgen/cmd/execgen/overloads_bin.go @@ -31,11 +31,13 @@ var binaryOpDecMethod = map[tree.BinaryOperator]string{ tree.Div: "Quo", tree.FloorDiv: "QuoInteger", tree.Mod: "Rem", + tree.Pow: "Pow", } var binaryOpFloatMethod = map[tree.BinaryOperator]string{ tree.FloorDiv: "math.Trunc", tree.Mod: "math.Mod", + tree.Pow: "math.Pow", } var binaryOpDecCtx = map[tree.BinaryOperator]string{ @@ -45,6 +47,7 @@ var binaryOpDecCtx = map[tree.BinaryOperator]string{ tree.Div: "DecimalCtx", tree.FloorDiv: "HighPrecisionCtx", tree.Mod: "HighPrecisionCtx", + tree.Pow: "DecimalCtx", } var compatibleCanonicalTypeFamilies = map[types.Family][]types.Family{ @@ -174,7 +177,7 @@ func registerBinOpOutputTypes() { binOpOutputTypes[tree.Plus][typePair{types.IntervalFamily, anyWidth, types.TimestampTZFamily, anyWidth}] = types.TimestampTZ // Other arithmetic binary operators. - for _, binOp := range []tree.BinaryOperator{tree.FloorDiv, tree.Mod} { + for _, binOp := range []tree.BinaryOperator{tree.FloorDiv, tree.Mod, tree.Pow} { binOpOutputTypes[binOp] = make(map[typePair]*types.T) populateBinOpIntOutputTypeOnIntArgs(binOp) binOpOutputTypes[binOp][typePair{types.FloatFamily, anyWidth, types.FloatFamily, anyWidth}] = types.Float @@ -317,7 +320,7 @@ func (c floatCustomizer) getBinOpAssignFunc() assignFunc { switch binOp { case tree.FloorDiv: computeBinOp = fmt.Sprintf("%s(float64(%s) / float64(%s))", binaryOpFloatMethod[binOp], leftElem, rightElem) - case tree.Mod: + case tree.Mod, tree.Pow: computeBinOp = fmt.Sprintf("%s(float64(%s), float64(%s))", binaryOpFloatMethod[binOp], leftElem, rightElem) default: computeBinOp = fmt.Sprintf("float64(%s) %s float64(%s)", leftElem, binOp, rightElem) @@ -329,6 +332,7 @@ func (c floatCustomizer) getBinOpAssignFunc() assignFunc { "ComputeBinOp": computeBinOp, } buf := strings.Builder{} + t := template.Must(template.New("").Parse(` { {{if .CheckRightIsZero}} @@ -339,6 +343,7 @@ func (c floatCustomizer) getBinOpAssignFunc() assignFunc { {{.Target}} = {{.ComputeBinOp}} } `)) + if err := t.Execute(&buf, args); err != nil { colexecerror.InternalError(err) } @@ -444,7 +449,46 @@ func (c intCustomizer) getBinOpAssignFunc() assignFunc { } } `)) + case tree.Pow: + var boundType, convType string + switch c.width { + case 16: + boundType = "Int16" + convType = "int16" + case 32: + boundType = "Int32" + convType = "int32" + case anyWidth: + boundType = "Int64" + convType = "int64" + default: + colexecerror.InternalError(fmt.Sprintf("unhandled integer width %d", c.width)) + } + args["Ctx"] = binaryOpDecCtx[binOp] + args["boundType"] = boundType + args["convType"] = convType + t = template.Must(template.New("").Parse(` + { + leftTmpDec, rightTmpDec := &_overloadHelper.tmpDec1, &_overloadHelper.tmpDec2 + leftTmpDec.SetInt64(int64({{.Left}})) + rightTmpDec.SetInt64(int64({{.Right}})) + if _, err := tree.{{.Ctx}}.Pow(leftTmpDec, leftTmpDec, rightTmpDec); err != nil { + colexecerror.ExpectedError(err) + } + resultInt, err := leftTmpDec.Int64() + if err != nil { + colexecerror.ExpectedError(tree.ErrIntOutOfRange) + } + boundType := "{{.boundType}}" + if boundType == "Int64" { + return resultInt + } else if (resultInt > math.Max{{.boundType}} || resultInt < math.Min{{.boundType}}) { + colexecerror.ExpectedError(tree.ErrIntOutOfRange) + } + {{.Target}} = {{.convType}}(resultInt) + } + `)) case tree.FloorDiv, tree.Mod: // Note that these operators have integer result. t = template.Must(template.New("").Parse(fmt.Sprintf(` diff --git a/pkg/sql/colexec/execgen/supported_bin_cmp_ops.go b/pkg/sql/colexec/execgen/supported_bin_cmp_ops.go index 250824521c68..ba47816ae070 100644 --- a/pkg/sql/colexec/execgen/supported_bin_cmp_ops.go +++ b/pkg/sql/colexec/execgen/supported_bin_cmp_ops.go @@ -24,6 +24,7 @@ var BinaryOpName = map[tree.BinaryOperator]string{ tree.Div: "Div", tree.FloorDiv: "FloorDiv", tree.Mod: "Mod", + tree.Pow: "Pow", tree.Concat: "Concat", tree.JSONFetchVal: "JSONFetchVal", } diff --git a/pkg/sql/logictest/testdata/logic_test/vectorize_overloads b/pkg/sql/logictest/testdata/logic_test/vectorize_overloads index b9b85e408c64..8e5855898665 100644 --- a/pkg/sql/logictest/testdata/logic_test/vectorize_overloads +++ b/pkg/sql/logictest/testdata/logic_test/vectorize_overloads @@ -109,6 +109,37 @@ EXPLAIN (VEC) SELECT _inet - _int2 FROM many_types └ *colexec.projMinusDatumInt16Op └ *colexec.colBatchScan +query T +EXPLAIN (VEC) SELECT _int2^_int4 FROM many_types +---- +│ +└ Node 1 + └ *colexec.projPowInt16Int32Op + └ *colexec.colBatchScan + +query T +EXPLAIN (VEC) SELECT _int2^_int FROM many_types +---- +│ +└ Node 1 + └ *colexec.projPowInt16Int64Op + └ *colexec.colBatchScan + +query T +EXPLAIN (VEC) SELECT _float^_float FROM many_types +---- +│ +└ Node 1 + └ *colexec.projPowFloat64Float64Op + └ *colexec.colBatchScan + +query T rowsort +SELECT (_float^_float)::STRING FROM many_types +---- +NULL +1.28998092100128 +1011.29924392386 + query T rowsort SELECT _inet - _int2 FROM many_types ---- @@ -283,6 +314,20 @@ EXPLAIN (VEC) SELECT _json -> _int2 FROM many_types └ *colexec.projJSONFetchValDatumInt16Op └ *colexec.colBatchScan + +query T rowsort +SELECT (_int2^_int2)::STRING FROM many_types WHERE _int2 < 10 AND _int2 < 10 +---- +4 + +statement error integer out of range +SELECT (_int2^_int2)::STRING FROM many_types + +query T rowsort +SELECT (_int2^_int4)::STRING FROM many_types WHERE _int2 < 10 AND _int4 < 10 +---- +4 + query T SELECT _json -> _int2 FROM many_types ----