From 28a61ef65fab83f9fc91af3c1f044921e7f07686 Mon Sep 17 00:00:00 2001 From: Takafumi Hirata Date: Wed, 10 Apr 2024 09:37:02 +0900 Subject: [PATCH] Implement unary minus operator --- internal/function_bind.go | 18 ++++++++++++++++++ internal/function_register.go | 1 + query_test.go | 21 ++++++++++++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/internal/function_bind.go b/internal/function_bind.go index 2a11901..930d2c5 100644 --- a/internal/function_bind.go +++ b/internal/function_bind.go @@ -3,6 +3,7 @@ package internal import ( "errors" "fmt" + "math" "sync" "github.com/goccy/go-json" @@ -184,6 +185,23 @@ func bindOpDiv(args ...Value) (Value, error) { return OP_DIV(args[0], args[1]) } +func bindUnaryMinus(args ...Value) (Value, error) { + if existsNull(args) { + return nil, nil + } + v, ok := args[0].(IntValue) + if ok { + i, err := v.ToInt64() + if err != nil { + return nil, err + } + if i <= math.MinInt64 { + return nil, fmt.Errorf("int64 overflow: -%d", i) + } + } + return SAFE_NEGATE(args[0]) +} + func bindEqual(args ...Value) (Value, error) { if existsNull(args) { return nil, nil diff --git a/internal/function_register.go b/internal/function_register.go index fcbb58c..bf74c47 100644 --- a/internal/function_register.go +++ b/internal/function_register.go @@ -13,6 +13,7 @@ var normalFuncs = []*FuncInfo{ {Name: "subtract", BindFunc: bindSub}, {Name: "multiply", BindFunc: bindMul}, {Name: "divide", BindFunc: bindOpDiv}, + {Name: "unary_minus", BindFunc: bindUnaryMinus}, {Name: "equal", BindFunc: bindEqual}, {Name: "not_equal", BindFunc: bindNotEqual}, {Name: "greater", BindFunc: bindGreater}, diff --git a/query_test.go b/query_test.go index de6c697..4290a32 100644 --- a/query_test.go +++ b/query_test.go @@ -68,10 +68,29 @@ UNION ALL expectedRows: [][]interface{}{{int64(1)}}, }, { - name: "unary minus operator", + name: "unary minus operator with literal", query: "SELECT -2", expectedRows: [][]interface{}{{int64(-2)}}, }, + { + name: "unary minus operator with column", + query: `WITH x AS ( + SELECT 2 AS i, 2.0 AS f + UNION ALL + SELECT -9223372036854775807, -9223372036854775807 + UNION ALL + SELECT NULL, -9223372036854775808 + ) SELECT -i, -f FROM x`, + expectedRows: [][]interface{}{ + {int64(-2), float64(-2.0)}, + {int64(9223372036854775807), float64(9223372036854775807)}, + {nil, float64(9223372036854775808)}}, + }, + { + name: "unary minus operator overflow", + query: "WITH x AS (SELECT -9223372036854775808 as v) SELECT -v FROM x", + expectedErr: "int64 overflow: --9223372036854775808", + }, { name: "bit not operator", query: "SELECT ~1",