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

sql: use custom boolean coercion logic in condition evaluation #768

Merged
merged 1 commit into from
Jun 24, 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
sql: use custom boolean coercion logic in condition evaluation
Signed-off-by: Miguel Molina <miguel@erizocosmi.co>
  • Loading branch information
erizocosmico committed Jun 24, 2019
commit 568f586c7eabaf707aab9bac564e45c8330ea044
4 changes: 4 additions & 0 deletions engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1230,6 +1230,10 @@ var queries = []struct {
`SELECT (NULL+1)`,
[]sql.Row{{nil}},
},
{
`SELECT * FROM mytable WHERE NULL AND i = 3`,
[]sql.Row{},
},
}

func TestQueries(t *testing.T) {
Expand Down
26 changes: 26 additions & 0 deletions sql/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package sql // import "github.com/src-d/go-mysql-server/sql"
import (
"fmt"
"io"
"math"
"time"

"gopkg.in/src-d/go-errors.v1"
)
Expand Down Expand Up @@ -218,3 +220,27 @@ type Lockable interface {
// available.
Unlock(ctx *Context, id uint32) error
}

// EvaluateCondition evaluates a condition, which is an expression whose value
// will be coerced to boolean.
func EvaluateCondition(ctx *Context, cond Expression, row Row) (bool, error) {
v, err := cond.Eval(ctx, row)
if err != nil {
return false, err
}

switch b := v.(type) {
case bool:
return b, nil
case int, int64, int32, int16, int8, uint, uint64, uint32, uint16, uint8:
return b != 0, nil
case time.Duration:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should a Duration or time really ever evaluate to false?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when it's 0, i guess

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But those are valid dates/durations. Anyway it's very minor; we should probably just do whatever MySQL do in these cases.

return int64(b) != 0, nil
case time.Time:
return b.UnixNano() != 0, nil
case float32, float64:
return int(math.Round(v.(float64))) != 0, nil
default:
return false, nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about the string:
select 1 from dual where "1";
basically it false, but for above string it's true for mysql.

}
}
4 changes: 2 additions & 2 deletions sql/plan/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,12 @@ func (i *FilterIter) Next() (sql.Row, error) {
return nil, err
}

result, err := i.cond.Eval(i.ctx, row)
ok, err := sql.EvaluateCondition(i.ctx, i.cond, row)
if err != nil {
return nil, err
}

if result == true {
if ok {
return row, nil
}
}
Expand Down
20 changes: 4 additions & 16 deletions sql/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -616,25 +616,13 @@ func (t booleanT) Convert(v interface{}) (interface{}, error) {
case bool:
return b, nil
case int, int64, int32, int16, int8, uint, uint64, uint32, uint16, uint8:
if b != 0 {
return true, nil
}
return false, nil
return b != 0, nil
case time.Duration:
if int64(b) != 0 {
return true, nil
}
return false, nil
return int64(b) != 0, nil
case time.Time:
if b.UnixNano() != 0 {
return true, nil
}
return false, nil
return b.UnixNano() != 0, nil
case float32, float64:
if int(math.Round(v.(float64))) != 0 {
return true, nil
}
return false, nil
return int(math.Round(v.(float64))) != 0, nil
case string:
return false, fmt.Errorf("unable to cast string to bool")

Expand Down
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy