Skip to content

Commit ecc2774

Browse files
committed
fix double negation
1 parent f7a3e38 commit ecc2774

File tree

2 files changed

+125
-7
lines changed

2 files changed

+125
-7
lines changed

enginetest/queries/script_queries.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,98 @@ type ScriptTestAssertion struct {
122122
// Unlike other engine tests, ScriptTests must be self-contained. No other tables are created outside the definition of
123123
// the tests.
124124
var ScriptTests = []ScriptTest{
125+
{
126+
// https://github.com/dolthub/dolt/issues/9927
127+
// https://github.com/dolthub/dolt/issues/9053
128+
Name: "double negation of integer minimum values",
129+
SetUpScript: []string{
130+
"CREATE TABLE t0(c0 BIGINT);",
131+
"INSERT INTO t0(c0) VALUES (-9223372036854775808);",
132+
"CREATE TABLE t1(c0 INT);",
133+
"INSERT INTO t1(c0) VALUES (-2147483648);",
134+
"CREATE TABLE t2(c0 SMALLINT);",
135+
"INSERT INTO t2(c0) VALUES (-32768);",
136+
"CREATE TABLE t3(c0 TINYINT);",
137+
"INSERT INTO t3(c0) VALUES (-128);",
138+
},
139+
Assertions: []ScriptTestAssertion{
140+
{
141+
Query: "SELECT 128;",
142+
Expected: []sql.Row{{uint64(128)}},
143+
ExpectedColumns: sql.Schema{{Name: "128", Type: types.Uint8}},
144+
},
145+
{
146+
Query: "SELECT -128;",
147+
Expected: []sql.Row{{int8(-128)}},
148+
ExpectedColumns: sql.Schema{{Name: "-128", Type: types.Int8}},
149+
},
150+
{
151+
Query: "SELECT -(-128);",
152+
Expected: []sql.Row{{int16(128)}},
153+
ExpectedColumns: sql.Schema{{Name: "-(-128)", Type: types.Int16}},
154+
},
155+
{
156+
Query: "SELECT -(-32768);",
157+
Expected: []sql.Row{{int32(32768)}},
158+
ExpectedColumns: sql.Schema{{Name: "-(-32768)", Type: types.Int32}},
159+
},
160+
{
161+
Query: "SELECT -(-2147483648);",
162+
Expected: []sql.Row{{int64(2147483648)}},
163+
ExpectedColumns: sql.Schema{{Name: "-(-2147483648)", Type: types.Int64}},
164+
},
165+
{
166+
Query: "SELECT -(-9223372036854775808)",
167+
Expected: []sql.Row{{"9223372036854775808"}},
168+
ExpectedColumns: sql.Schema{{Name: "-(-9223372036854775808)", Type: types.InternalDecimalType}},
169+
},
170+
{
171+
Query: "SELECT -t0.c0 FROM t0;",
172+
ExpectedErr: sql.ErrValueOutOfRange,
173+
},
174+
{
175+
Query: "SELECT -t1.c0 FROM t1;",
176+
Expected: []sql.Row{{2147483648}},
177+
},
178+
{
179+
Query: "SELECT -t2.c0 FROM t2;",
180+
Expected: []sql.Row{{32768}},
181+
},
182+
{
183+
Query: "SELECT -t3.c0 FROM t3;",
184+
Expected: []sql.Row{{128}},
185+
},
186+
{
187+
Query: "SELECT -(-t1.c0 + 1) FROM t1;",
188+
Expected: []sql.Row{{-2147483649}},
189+
},
190+
{
191+
Query: "SELECT -(-(t2.c0 - 1)) FROM t2;",
192+
Expected: []sql.Row{{-32769}},
193+
},
194+
{
195+
Query: "SELECT -(-t3.c0 * 2) FROM t3;",
196+
Expected: []sql.Row{{-256}},
197+
},
198+
{
199+
Query: "SELECT -(-(-128));",
200+
Expected: []sql.Row{{int8(-128)}},
201+
},
202+
{
203+
Query: "SELECT -(-(-(-128)));",
204+
Expected: []sql.Row{{int16(128)}},
205+
},
206+
{
207+
Query: "SELECT -(-NULL);",
208+
Expected: []sql.Row{{nil}},
209+
},
210+
{
211+
Query: "SELECT -(-CAST(-128 AS SIGNED));",
212+
Expected: []sql.Row{{int64(-128)}},
213+
ExpectedColumns: sql.Schema{{Name: "-(-CAST(-128 AS SIGNED))", Type: types.Int64}},
214+
},
215+
},
216+
},
125217
{
126218
// https://github.com/dolthub/dolt/issues/9865
127219
Name: "Stored procedure containing a transaction does not return EOF",

sql/expression/arithmetic.go

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import (
2626
"github.com/dolthub/vitess/go/mysql"
2727
"github.com/dolthub/vitess/go/vt/sqlparser"
2828
"github.com/shopspring/decimal"
29-
errors "gopkg.in/src-d/go-errors.v1"
29+
"gopkg.in/src-d/go-errors.v1"
3030

3131
"github.com/dolthub/go-mysql-server/sql"
3232
"github.com/dolthub/go-mysql-server/sql/types"
@@ -669,14 +669,15 @@ func mult(lval, rval interface{}) (interface{}, error) {
669669
// UnaryMinus is an unary minus operator.
670670
type UnaryMinus struct {
671671
UnaryExpression
672+
typ sql.Type
672673
}
673674

674675
var _ sql.Expression = (*UnaryMinus)(nil)
675676
var _ sql.CollationCoercible = (*UnaryMinus)(nil)
676677

677678
// NewUnaryMinus creates a new UnaryMinus expression node.
678679
func NewUnaryMinus(child sql.Expression) *UnaryMinus {
679-
return &UnaryMinus{UnaryExpression{Child: child}}
680+
return &UnaryMinus{UnaryExpression{Child: child}, child.Type()}
680681
}
681682

682683
// Eval implements the sql.Expression interface.
@@ -724,6 +725,9 @@ func (e *UnaryMinus) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
724725
return -n, nil
725726
case int64:
726727
if n == math.MinInt64 {
728+
if _, ok := e.Child.(*Literal); ok {
729+
return decimal.NewFromInt(n).Neg(), nil
730+
}
727731
return nil, sql.ErrValueOutOfRange.New("BIGINT", fmt.Sprintf("%d", n))
728732
}
729733
return -n, nil
@@ -759,20 +763,42 @@ func (e *UnaryMinus) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
759763

760764
// Type implements the sql.Expression interface.
761765
func (e *UnaryMinus) Type() sql.Type {
762-
typ := e.Child.Type()
763-
if !types.IsNumber(typ) {
766+
// Literals can overflow their types on unary minus, so we need to promote them
767+
if lit, ok := e.Child.(*Literal); ok {
768+
v := lit.Value()
769+
switch n := v.(type) {
770+
case int8:
771+
if n == math.MinInt8 {
772+
e.typ = types.Int16
773+
}
774+
case int16:
775+
if n == math.MinInt16 {
776+
e.typ = types.Int32
777+
}
778+
case int32:
779+
if n == math.MinInt32 {
780+
e.typ = types.Int64
781+
}
782+
case int64:
783+
if n == math.MinInt64 {
784+
e.typ = types.InternalDecimalType
785+
}
786+
}
787+
}
788+
789+
if !types.IsNumber(e.typ) {
764790
return types.Float64
765791
}
766792

767-
if typ == types.Uint32 {
793+
if e.typ == types.Uint32 {
768794
return types.Int32
769795
}
770796

771-
if typ == types.Uint64 {
797+
if e.typ == types.Uint64 {
772798
return types.Int64
773799
}
774800

775-
return e.Child.Type()
801+
return e.typ
776802
}
777803

778804
// CollationCoercibility implements the interface sql.CollationCoercible.

0 commit comments

Comments
 (0)