Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

evalengine: virtual machine #12369

Merged
merged 42 commits into from
Mar 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
e649e95
go: add a slices2 package
vmg Mar 6, 2023
c3842f4
evalengine: compiler [wip]
vmg Mar 6, 2023
1bc1846
evalengine: fix test helpers
vmg Mar 6, 2023
0a7fe36
evalengine/compiler: Add support for REPEAT
dbussink Mar 6, 2023
e689fac
evalengine/compiler: Add support for base64 functions
dbussink Mar 6, 2023
12697d1
evalengine/compiler: Implement UPPER / LOWER
dbussink Mar 6, 2023
679e494
evalengine/compiler: Implement string length functions
dbussink Mar 6, 2023
469f914
evalengine/compiler: Implement ASCII() function
dbussink Mar 6, 2023
c7b3da3
evalengine/compiler: Implement LIKE support
dbussink Mar 7, 2023
1afc00c
evalengine/compiler: fix naming for instructions
vmg Mar 7, 2023
3e4d778
evalengine/compiler: use new collation API
vmg Mar 7, 2023
1d4f093
evalengine/compiler: implement multi-comparisons
vmg Mar 7, 2023
196d4a5
evalengine/compiler: implement JSON_ARRAY
vmg Mar 8, 2023
2ef498c
Fix issues after rebasing
dbussink Mar 8, 2023
b49e88c
evalengine/compiler: Implement hex() and convert using
dbussink Mar 8, 2023
0447114
evalengine/compiler: implement JSON_OBJECT
vmg Mar 8, 2023
9614703
compiler: add support for tuple comparisons
vmg Mar 8, 2023
c802f54
evalengine/compiler: arrange in separate files
vmg Mar 8, 2023
9834fc3
evalengine/compiler: Implement COLLATION function
dbussink Mar 9, 2023
1f16caf
evalengine/compiler: Implement CEIL
dbussink Mar 9, 2023
500bcf9
evalengine/compiler: IS expressions and JSON_KEYS
vmg Mar 8, 2023
9cff5d7
evalengine: fix IS and CEIL corner cases
vmg Mar 9, 2023
e2c84d2
evalengine/compiler: implement IN
vmg Mar 10, 2023
a981906
evalengine/compiler: implement WEIGHT_STRING
vmg Mar 10, 2023
1f513a3
evalengine/compiler: optimize null checks
vmg Mar 10, 2023
85b97bf
evalengine/compiler: test for runtime errors
vmg Mar 10, 2023
35ad0fe
evalengine: Add support for FLOOR().
dbussink Mar 10, 2023
35a9998
evalengine: Add support for ABS()
dbussink Mar 10, 2023
d71e051
evalengine: Implement trigonometry functions
dbussink Mar 11, 2023
7cd35c2
evalengine: simplify test case generation
vmg Mar 13, 2023
07d3003
evalengine: add missing headers
vmg Mar 13, 2023
9ff967c
evalengine: sizegen
vmg Mar 13, 2023
26871f5
slices2: update licensing
vmg Mar 13, 2023
1bc5a96
evalengine: add documentation
vmg Mar 15, 2023
5efd9f0
Move normalization logic as it's test only
dbussink Mar 15, 2023
e0fca5e
evalengine/compiler: Add missing COT to compiler.
dbussink Mar 16, 2023
310d572
evalengine/compiler: Fix flags for arithmatic operations
dbussink Mar 16, 2023
ffaa737
refactor comparisons
systay Mar 16, 2023
96c5759
no need to pass in err to method
systay Mar 16, 2023
44328b9
evalengine/compiler: remove redundant constants
vmg Mar 16, 2023
10ab0a1
evalengine/compiler: de-duplicate math functions
vmg Mar 16, 2023
45f6497
evalengine: Add additional arithmetic tests and fix edge cases
dbussink Mar 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions go/slices2/slices.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
Copyright 2023 The Vitess Authors.

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,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Package slices2 contains generic Slice helpers;
// Some of this code is sourced from https://github.com/luraim/fun (Apache v2)
package slices2

// All returns true if all elements return true for given predicate
func All[T any](s []T, fn func(T) bool) bool {
for _, e := range s {
if !fn(e) {
return false
}
}
return true
}

// Any returns true if at least one element returns true for given predicate
func Any[T any](s []T, fn func(T) bool) bool {
for _, e := range s {
if fn(e) {
return true
}
}
return false
}
3 changes: 1 addition & 2 deletions go/vt/dbconnpool/connection_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,14 @@ object to pool these DBConnections.
package dbconnpool

import (
"context"
"errors"
"net"
"sync"
"time"

"vitess.io/vitess/go/netutil"

"context"

"vitess.io/vitess/go/pools"
"vitess.io/vitess/go/stats"
"vitess.io/vitess/go/vt/dbconfigs"
Expand Down
2 changes: 1 addition & 1 deletion go/vt/vtgate/evalengine/api_arithmetic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ func TestArithmetics(t *testing.T) {
// testing for overflow of float64
v1: NewFloat64(math.MaxFloat64),
v2: NewFloat64(0.5),
err: dataOutOfRangeError(math.MaxFloat64, 0.5, "BIGINT", "/").Error(),
err: dataOutOfRangeError(math.MaxFloat64, 0.5, "DOUBLE", "/").Error(),
}},
}, {
operator: "*",
Expand Down
29 changes: 0 additions & 29 deletions go/vt/vtgate/evalengine/api_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ limitations under the License.
package evalengine

import (
"fmt"
"strconv"

"vitess.io/vitess/go/mysql/collations"
"vitess.io/vitess/go/sqltypes"
vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
"vitess.io/vitess/go/vt/sqlparser"
Expand Down Expand Up @@ -175,28 +171,3 @@ func ToNative(v sqltypes.Value) (any, error) {
}
return out, err
}

func NormalizeValue(v sqltypes.Value, coll collations.ID) string {
typ := v.Type()
if typ == sqltypes.Null {
return "NULL"
}
if typ == sqltypes.VarChar && coll == collations.CollationBinaryID {
return fmt.Sprintf("VARBINARY(%q)", v.Raw())
}
if v.IsQuoted() || typ == sqltypes.Bit {
return fmt.Sprintf("%v(%q)", typ, v.Raw())
}
if typ == sqltypes.Float32 || typ == sqltypes.Float64 {
var bitsize = 64
if typ == sqltypes.Float32 {
bitsize = 32
}
f, err := strconv.ParseFloat(v.RawStr(), bitsize)
if err != nil {
panic(err)
}
return fmt.Sprintf("%v(%s)", typ, FormatFloat(typ, f))
}
return fmt.Sprintf("%v(%s)", typ, v.Raw())
}
120 changes: 120 additions & 0 deletions go/vt/vtgate/evalengine/arena.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
Copyright 2023 The Vitess Authors.

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,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package evalengine
dbussink marked this conversation as resolved.
Show resolved Hide resolved

import (
"vitess.io/vitess/go/mysql/collations"
"vitess.io/vitess/go/sqltypes"
"vitess.io/vitess/go/vt/vtgate/evalengine/internal/decimal"
)

// Arena is an arena memory allocator for eval types.
// It allocates the types from reusable slices to prevent heap allocations.
// After each evaluation execution, (*Arena).reset() should be called to reset the arena.
type Arena struct {
dbussink marked this conversation as resolved.
Show resolved Hide resolved
aInt64 []evalInt64
aUint64 []evalUint64
aFloat64 []evalFloat
aDecimal []evalDecimal
aBytes []evalBytes
}

func (a *Arena) reset() {
a.aInt64 = a.aInt64[:0]
a.aUint64 = a.aUint64[:0]
a.aFloat64 = a.aFloat64[:0]
a.aDecimal = a.aDecimal[:0]
a.aBytes = a.aBytes[:0]
}

func (a *Arena) newEvalDecimalWithPrec(dec decimal.Decimal, prec int32) *evalDecimal {
if cap(a.aDecimal) > len(a.aDecimal) {
a.aDecimal = a.aDecimal[:len(a.aDecimal)+1]
} else {
a.aDecimal = append(a.aDecimal, evalDecimal{})
vmg marked this conversation as resolved.
Show resolved Hide resolved
}
val := &a.aDecimal[len(a.aDecimal)-1]
val.dec = dec
val.length = prec
return val
}

func (a *Arena) newEvalDecimal(dec decimal.Decimal, m, d int32) *evalDecimal {
if m == 0 && d == 0 {
return a.newEvalDecimalWithPrec(dec, -dec.Exponent())
}
return a.newEvalDecimalWithPrec(dec.Clamp(m-d, d), d)
}

func (a *Arena) newEvalInt64(i int64) *evalInt64 {
if cap(a.aInt64) > len(a.aInt64) {
a.aInt64 = a.aInt64[:len(a.aInt64)+1]
} else {
a.aInt64 = append(a.aInt64, evalInt64{})
}
val := &a.aInt64[len(a.aInt64)-1]
val.i = i
return val
}

func (a *Arena) newEvalUint64(u uint64) *evalUint64 {
if cap(a.aUint64) > len(a.aUint64) {
a.aUint64 = a.aUint64[:len(a.aUint64)+1]
} else {
a.aUint64 = append(a.aUint64, evalUint64{})
}
val := &a.aUint64[len(a.aUint64)-1]
val.u = u
val.hexLiteral = false
return val
}

func (a *Arena) newEvalFloat(f float64) *evalFloat {
if cap(a.aFloat64) > len(a.aFloat64) {
a.aFloat64 = a.aFloat64[:len(a.aFloat64)+1]
} else {
a.aFloat64 = append(a.aFloat64, evalFloat{})
}
val := &a.aFloat64[len(a.aFloat64)-1]
val.f = f
return val
}

func (a *Arena) newEvalBytesEmpty() *evalBytes {
if cap(a.aBytes) > len(a.aBytes) {
a.aBytes = a.aBytes[:len(a.aBytes)+1]
} else {
a.aBytes = append(a.aBytes, evalBytes{})
}
return &a.aBytes[len(a.aBytes)-1]
}

func (a *Arena) newEvalBinary(raw []byte) *evalBytes {
b := a.newEvalBytesEmpty()
b.tt = int16(sqltypes.VarBinary)
b.col = collationBinary
b.bytes = raw
return b
}

func (a *Arena) newEvalText(raw []byte, tc collations.TypedCollation) *evalBytes {
b := a.newEvalBytesEmpty()
b.tt = int16(sqltypes.VarChar)
b.col = tc
b.bytes = raw
return b
}
15 changes: 7 additions & 8 deletions go/vt/vtgate/evalengine/arithmetic.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package evalengine

import (
"math"
"strings"

"golang.org/x/exp/constraints"
Expand Down Expand Up @@ -193,7 +194,7 @@ func mathSub_iu(v1 int64, v2 uint64) (*evalUint64, error) {
}

func mathSub_iu0(v1 int64, v2 uint64) (uint64, error) {
if v1 < 0 || v1 < int64(v2) {
if v1 < 0 {
return 0, dataOutOfRangeError(v1, v2, "BIGINT UNSIGNED", "-")
}
return mathSub_uu0(uint64(v1), v2)
Expand All @@ -218,12 +219,12 @@ func mathSub_ui(v1 uint64, v2 int64) (*evalUint64, error) {
}

func mathSub_ui0(v1 uint64, v2 int64) (uint64, error) {
if int64(v1) < v2 && v2 > 0 {
if v2 > 0 && v1 < uint64(v2) {
return 0, dataOutOfRangeError(v1, v2, "BIGINT UNSIGNED", "-")
}
// uint - (- int) = uint + int
if v2 < 0 {
return mathAdd_ui0(v1, -v2)
return mathAdd_uu0(v1, uint64(-v2))
}
return mathSub_uu0(v1, uint64(v2))
}
Expand All @@ -237,7 +238,7 @@ func mathMul_ui0(v1 uint64, v2 int64) (uint64, error) {
if v1 == 0 || v2 == 0 {
return 0, nil
}
if v2 < 0 || int64(v1) < 0 {
if v2 < 0 {
return 0, dataOutOfRangeError(v1, v2, "BIGINT UNSIGNED", "*")
}
return mathMul_uu0(v1, uint64(v2))
Expand Down Expand Up @@ -405,11 +406,9 @@ func mathDiv_ff(v1, v2 float64) (eval, error) {

func mathDiv_ff0(v1, v2 float64) (float64, error) {
result := v1 / v2
divisorLessThanOne := v2 < 1
resultMismatch := v2*result != v1

if divisorLessThanOne && resultMismatch {
return 0, dataOutOfRangeError(v1, v2, "BIGINT", "/")
if math.IsInf(result, 1) || math.IsInf(result, -1) {
return 0, dataOutOfRangeError(v1, v2, "DOUBLE", "/")
}
return result, nil
}
Expand Down
Loading