Skip to content
This repository has been archived by the owner on Jan 28, 2021. It is now read-only.

Zachmu/bug fixes to contribute #784

Merged
merged 16 commits into from
Jul 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
173 changes: 170 additions & 3 deletions engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,90 @@ var queries = []struct {
"SELECT i FROM mytable;",
[]sql.Row{{int64(1)}, {int64(2)}, {int64(3)}},
},
{
"SELECT i + 1 FROM mytable;",
[]sql.Row{{int64(2)}, {int64(3)}, {int64(4)}},
},
{
"SELECT -i FROM mytable;",
[]sql.Row{{int64(-1)}, {int64(-2)}, {int64(-3)}},
},
{
"SELECT i FROM mytable where -i = -2;",
[]sql.Row{{int64(2)}},
},
{
"SELECT i FROM mytable WHERE i = 2;",
[]sql.Row{{int64(2)}},
},
{
"SELECT i FROM mytable WHERE i > 2;",
[]sql.Row{{int64(3)}},
},
{
"SELECT i FROM mytable WHERE i < 2;",
[]sql.Row{{int64(1)}},
},
{
"SELECT i FROM mytable WHERE i <> 2;",
[]sql.Row{{int64(1)}, {int64(3)}},
},
{
"SELECT f32 FROM floattable WHERE f64 = 2.0;",
[]sql.Row{{float32(2.0)}},
},
{
"SELECT f32 FROM floattable WHERE f64 < 2.0;",
[]sql.Row{{float32(-1.0)}, {float32(-1.5)}, {float32(1.0)}, {float32(1.5)}},
},
{
"SELECT f32 FROM floattable WHERE f64 > 2.0;",
[]sql.Row{{float32(2.5)}},
},
{
"SELECT f32 FROM floattable WHERE f64 <> 2.0;",
[]sql.Row{{float32(-1.0)}, {float32(-1.5)}, {float32(1.0)}, {float32(1.5)}, {float32(2.5)}},
},
{
"SELECT f64 FROM floattable WHERE f32 = 2.0;",
[]sql.Row{{float64(2.0)}},
},
{
"SELECT f64 FROM floattable WHERE f32 = -1.5;",
[]sql.Row{{float64(-1.5)}},
},
{
"SELECT f64 FROM floattable WHERE -f32 = -2.0;",
[]sql.Row{{float64(2.0)}},
},
{
"SELECT f64 FROM floattable WHERE f32 < 2.0;",
[]sql.Row{{float64(-1.0)}, {float64(-1.5)}, {float64(1.0)}, {float64(1.5)}},
},
{
"SELECT f64 FROM floattable WHERE f32 > 2.0;",
[]sql.Row{{float64(2.5)}},
},
{
"SELECT f64 FROM floattable WHERE f32 <> 2.0;",
[]sql.Row{{float64(-1.0)}, {float64(-1.5)}, {float64(1.0)}, {float64(1.5)}, {float64(2.5)}},
},
{
"SELECT f32 FROM floattable ORDER BY f64;",
[]sql.Row{{float32(-1.5)}, {float32(-1.0)}, {float32(1.0)}, {float32(1.5)}, {float32(2.0)}, {float32(2.5)}},
},
{
"SELECT i FROM mytable ORDER BY i DESC;",
[]sql.Row{{int64(3)}, {int64(2)}, {int64(1)}},
},
{
"SELECT i FROM mytable WHERE 'hello';",
[]sql.Row{},
},
{
"SELECT i FROM mytable WHERE not 'hello';",
[]sql.Row{{int64(1)}, {int64(2)}, {int64(3)}},
},
{
"SELECT i FROM mytable WHERE s = 'first row' ORDER BY i DESC;",
[]sql.Row{{int64(1)}},
Expand All @@ -64,6 +140,38 @@ var queries = []struct {
"SELECT i FROM mytable ORDER BY i LIMIT 2,100;",
[]sql.Row{{int64(3)}},
},
{
"SELECT i FROM niltable WHERE b IS NULL",
[]sql.Row{{int64(2)}, {nil}},
},
{
"SELECT i FROM niltable WHERE b IS NOT NULL",
[]sql.Row{{int64(1)}, {nil}, {int64(4)}},
},
{
"SELECT i FROM niltable WHERE b",
[]sql.Row{{int64(1)}, {int64(4)}},
},
{
"SELECT i FROM niltable WHERE NOT b",
[]sql.Row{{nil}},
},
{
"SELECT i FROM niltable WHERE b IS TRUE",
[]sql.Row{{int64(1)}, {int64(4)}},
},
{
"SELECT i FROM niltable WHERE b IS NOT TRUE",
[]sql.Row{{int64(2)}, {nil}, {nil}},
},
{
"SELECT f FROM niltable WHERE b IS FALSE",
[]sql.Row{{3.0}},
},
{
"SELECT i FROM niltable WHERE b IS NOT FALSE",
[]sql.Row{{int64(1)}, {int64(2)}, {int64(4)}, {nil}},
},
{
"SELECT COUNT(*) FROM mytable;",
[]sql.Row{{int64(3)}},
Expand Down Expand Up @@ -593,6 +701,8 @@ var queries = []struct {
{"othertable", "InnoDB", "10", "Fixed", int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), nil, nil, nil, "utf8_bin", nil, nil},
{"tabletest", "InnoDB", "10", "Fixed", int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), nil, nil, nil, "utf8_bin", nil, nil},
{"bigtable", "InnoDB", "10", "Fixed", int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), nil, nil, nil, "utf8_bin", nil, nil},
{"floattable", "InnoDB", "10", "Fixed", int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), nil, nil, nil, "utf8_bin", nil, nil},
{"niltable", "InnoDB", "10", "Fixed", int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), nil, nil, nil, "utf8_bin", nil, nil},
},
},
{
Expand All @@ -601,6 +711,8 @@ var queries = []struct {
{"mytable", "InnoDB", "10", "Fixed", int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), nil, nil, nil, "utf8_bin", nil, nil},
{"othertable", "InnoDB", "10", "Fixed", int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), nil, nil, nil, "utf8_bin", nil, nil},
{"bigtable", "InnoDB", "10", "Fixed", int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), nil, nil, nil, "utf8_bin", nil, nil},
{"floattable", "InnoDB", "10", "Fixed", int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), nil, nil, nil, "utf8_bin", nil, nil},
{"niltable", "InnoDB", "10", "Fixed", int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), nil, nil, nil, "utf8_bin", nil, nil},
},
},
{
Expand Down Expand Up @@ -741,6 +853,8 @@ var queries = []struct {
{"othertable"},
{"tabletest"},
{"bigtable"},
{"floattable"},
{"niltable"},
},
},
{
Expand All @@ -766,6 +880,10 @@ var queries = []struct {
{"i2"},
{"t"},
{"n"},
{"f32"},
{"f64"},
{"b"},
{"f"},
},
},
{
Expand All @@ -781,6 +899,10 @@ var queries = []struct {
{"i2"},
{"t"},
{"n"},
{"f32"},
{"f64"},
{"b"},
{"f"},
},
},
{
Expand All @@ -796,6 +918,10 @@ var queries = []struct {
{"i2"},
{"t"},
{"n"},
{"f32"},
{"f64"},
{"b"},
{"f"},
},
},
{
Expand Down Expand Up @@ -830,6 +956,8 @@ var queries = []struct {
{"othertable", "InnoDB", "10", "Fixed", int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), nil, nil, nil, "utf8_bin", nil, nil},
{"tabletest", "InnoDB", "10", "Fixed", int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), nil, nil, nil, "utf8_bin", nil, nil},
{"bigtable", "InnoDB", "10", "Fixed", int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), nil, nil, nil, "utf8_bin", nil, nil},
{"floattable", "InnoDB", "10", "Fixed", int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), nil, nil, nil, "utf8_bin", nil, nil},
{"niltable", "InnoDB", "10", "Fixed", int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), int64(0), nil, nil, nil, "utf8_bin", nil, nil},
},
},
{
Expand Down Expand Up @@ -941,6 +1069,8 @@ var queries = []struct {
{"othertable"},
{"tabletest"},
{"bigtable"},
{"floattable"},
{"niltable"},
},
},
{
Expand All @@ -950,6 +1080,8 @@ var queries = []struct {
{"othertable", "BASE TABLE"},
{"tabletest", "BASE TABLE"},
{"bigtable", "BASE TABLE"},
{"floattable", "BASE TABLE"},
{"niltable", "BASE TABLE"},
},
},
{
Expand All @@ -964,6 +1096,8 @@ var queries = []struct {
{"mytable"},
{"othertable"},
{"bigtable"},
{"floattable"},
{"niltable"},
},
},
{
Expand Down Expand Up @@ -1873,9 +2007,9 @@ func TestInnerNestedInNaturalJoins(t *testing.T) {

insertRows(
t, table3,
sql.NewRow(int32(1), float64(2.3), "table3"),
sql.NewRow(int32(2), float64(2.3), "table3"),
sql.NewRow(int32(30), float64(2.3), "table3"),
sql.NewRow(int32(1), float64(2.2), "table3"),
sql.NewRow(int32(2), float64(2.2), "table3"),
sql.NewRow(int32(30), float64(2.2), "table3"),
)

db := mem.NewDatabase("mydb")
Expand Down Expand Up @@ -2002,11 +2136,44 @@ func newEngineWithParallelism(t *testing.T, parallelism int) *sqle.Engine {
sql.NewRow("b", int64(9)),
)

floatTable := mem.NewPartitionedTable("floattable", sql.Schema{
{Name: "i", Type: sql.Int64, Source: "floattable"},
{Name: "f32", Type: sql.Float32, Source: "floattable"},
{Name: "f64", Type: sql.Float64, Source: "floattable"},
}, testNumPartitions)

insertRows(
t, floatTable,
sql.NewRow(1, float32(1.0), float64(1.0)),
sql.NewRow(2, float32(1.5), float64(1.5)),
sql.NewRow(3, float32(2.0), float64(2.0)),
sql.NewRow(4, float32(2.5), float64(2.5)),
sql.NewRow(-1, float32(-1.0), float64(-1.0)),
sql.NewRow(-2, float32(-1.5), float64(-1.5)),
)

nilTable := mem.NewPartitionedTable("niltable", sql.Schema{
{Name: "i", Type: sql.Int64, Source: "niltable", Nullable: true},
{Name: "b", Type: sql.Boolean, Source: "niltable", Nullable: true},
{Name: "f", Type: sql.Float64, Source: "niltable", Nullable: true},
}, testNumPartitions)

insertRows(
t, nilTable,
sql.NewRow(int64(1), true, float64(1.0)),
sql.NewRow(int64(2), nil, float64(2.0)),
sql.NewRow(nil, false, float64(3.0)),
sql.NewRow(int64(4), true, nil),
sql.NewRow(nil, nil, nil),
)

db := mem.NewDatabase("mydb")
db.AddTable("mytable", table)
db.AddTable("othertable", table2)
db.AddTable("tabletest", table3)
db.AddTable("bigtable", bigtable)
db.AddTable("floattable", floatTable)
db.AddTable("niltable", nilTable)

db2 := mem.NewDatabase("foo")
db2.AddTable("other_table", table4)
Expand Down
15 changes: 4 additions & 11 deletions sql/analyzer/optimization_rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,27 +380,20 @@ func evalFilter(ctx *sql.Context, a *Analyzer, node sql.Node) (sql.Node, error)
return e.Left, nil
}

return e, nil
case *expression.Literal, expression.Tuple:
return e, nil
default:
if !isEvaluable(e) {
return e, nil
}

if _, ok := e.(*expression.Literal); ok {
return e, nil
}

// All other expressions types can be evaluated once and turned into literals for the rest of query execution
val, err := e.Eval(ctx, nil)
if err != nil {
return e, nil
}

val, err = sql.Boolean.Convert(val)
if err != nil {
return e, nil
}

return expression.NewLiteral(val.(bool), sql.Boolean), nil
return expression.NewLiteral(val, e.Type()), nil
}
})
if err != nil {
Expand Down
78 changes: 78 additions & 0 deletions sql/expression/istrue.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package expression

import (
"errors"
"github.com/src-d/go-mysql-server/sql"
)

// IsTrue is an expression that checks if an expression is true.
type IsTrue struct {
UnaryExpression
invert bool
}

const IsTrueStr = "IS TRUE"
const IsFalseStr = "IS FALSE"

// NewIsTrue creates a new IsTrue expression.
func NewIsTrue(child sql.Expression) *IsTrue {
return &IsTrue{UnaryExpression: UnaryExpression{child}}
}

// NewIsFalse creates a new IsTrue expression with its boolean sense inverted (IsFalse, effectively).
func NewIsFalse(child sql.Expression) *IsTrue {
return &IsTrue{UnaryExpression: UnaryExpression{child}, invert: true}
}

// Type implements the Expression interface.
func (*IsTrue) Type() sql.Type {
return sql.Boolean
}

// IsNullable implements the Expression interface.
func (*IsTrue) IsNullable() bool {
return false
}

// Eval implements the Expression interface.
func (e *IsTrue) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
v, err := e.Child.Eval(ctx, row)
if err != nil {
return nil, err
}

var boolVal interface{}
if v == nil {
return false, nil
} else {
boolVal, err = sql.Boolean.Convert(v)
if err != nil {
return nil, err
}
}

if e.invert {
return !boolVal.(bool), nil
}
return boolVal, nil
}

func (e *IsTrue) String() string {
isStr := IsTrueStr
if e.invert {
isStr = IsFalseStr
}
return e.Child.String() + " " + isStr
}

// WithChildren implements the Expression interface.
func (e *IsTrue) WithChildren(children ...sql.Expression) (sql.Expression, error) {
if len(children) != 1 {
return nil, errors.New("incorrect number of children")
}

if e.invert {
return NewIsFalse(children[0]), nil
}
return NewIsTrue(children[0]), nil
}
Loading