Skip to content

Commit

Permalink
sql: expression: function: Add CEIL, CEILING, FLOOR. [Fixes Half src-…
Browse files Browse the repository at this point in the history
…d#393]

Signed-off-by: Theodoros Zarkopafilis Ntakouris <zarkopafilis@gmail.com>
  • Loading branch information
ntakouris committed Oct 4, 2018
1 parent 1fa8e98 commit 865b69a
Show file tree
Hide file tree
Showing 4 changed files with 455 additions and 0 deletions.
37 changes: 37 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,19 +1,56 @@
module gopkg.in/src-d/go-mysql-server.v0

require (
github.com/BurntSushi/toml v0.3.1 // indirect
github.com/CAFxX/gcnotifier v0.0.0-20170518020117-39b0596a2da3 // indirect
github.com/DataDog/datadog-go v0.0.0-20180822151419-281ae9f2d895 // indirect
github.com/StackExchange/wmi v0.0.0-20180725035823-b12b22c5341f // indirect
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da // indirect
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 // indirect
github.com/boltdb/bolt v1.3.1
github.com/cespare/xxhash v1.1.0 // indirect
github.com/circonus-labs/circonus-gometrics v2.2.4+incompatible // indirect
github.com/circonus-labs/circonusllhist v0.0.0-20180430145027-5eb751da55c6 // indirect
github.com/go-ole/go-ole v1.2.1 // indirect
github.com/gogo/protobuf v1.1.1 // indirect
github.com/google/go-cmp v0.2.0 // indirect
github.com/gorilla/context v1.1.1 // indirect
github.com/gorilla/handlers v1.4.0 // indirect
github.com/gorilla/mux v1.6.2 // indirect
github.com/hashicorp/consul v1.2.3 // indirect
github.com/hashicorp/go-cleanhttp v0.5.0 // indirect
github.com/hashicorp/go-immutable-radix v1.0.0 // indirect
github.com/hashicorp/go-msgpack v0.0.0-20150518234257-fa3f63826f7c // indirect
github.com/hashicorp/go-multierror v1.0.0 // indirect
github.com/hashicorp/go-retryablehttp v0.0.0-20180718195005-e651d75abec6 // indirect
github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86 // indirect
github.com/hashicorp/memberlist v0.1.0 // indirect
github.com/hashicorp/serf v0.8.1 // indirect
github.com/hashicorp/yamux v0.0.0-20180917205041-7221087c3d28 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/miekg/dns v1.0.12 // indirect
github.com/mitchellh/hashstructure v1.0.0
github.com/opentracing/opentracing-go v1.0.2
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c // indirect
github.com/pelletier/go-toml v1.2.0 // indirect
github.com/pilosa/pilosa v1.1.0
github.com/pkg/errors v0.8.0 // indirect
github.com/prometheus/client_golang v0.8.0 // indirect
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 // indirect
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e // indirect
github.com/prometheus/procfs v0.0.0-20180920065004-418d78d0b9a7 // indirect
github.com/satori/go.uuid v1.2.0 // indirect
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect
github.com/shirou/gopsutil v2.17.12+incompatible // indirect
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect
github.com/sirupsen/logrus v1.1.0
github.com/spf13/cast v1.2.0
github.com/stretchr/testify v1.2.2
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 // indirect
golang.org/x/net v0.0.0-20180926154720-4dfa2610cdf3 // indirect
google.golang.org/grpc v1.15.0 // indirect
gopkg.in/src-d/go-errors.v1 v1.0.0
gopkg.in/src-d/go-vitess.v1 v1.1.0
gopkg.in/vmihailenco/msgpack.v2 v2.9.1 // indirect
gopkg.in/yaml.v2 v2.2.1
)
145 changes: 145 additions & 0 deletions sql/expression/function/ceil_round_floor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package function

import (
"fmt"
"gopkg.in/src-d/go-mysql-server.v0/sql"
"gopkg.in/src-d/go-mysql-server.v0/sql/expression"
"math"
"reflect"
)

// Ceil returns the smallest integer value not less than X.
type Ceil struct {
expression.UnaryExpression
}

func (c *Ceil) Resolved() bool {
return c.Child.Resolved()
}

func (c *Ceil) IsNullable() bool {
return c.Child.IsNullable()
}

func (c *Ceil) Children() []sql.Expression {
return c.Child.Children()
}

func NewCeil(array sql.Expression) sql.Expression {
return &Ceil{expression.UnaryExpression{Child: array}}
}

func (c *Ceil) Type() sql.Type {
return c.Child.Type()
}

func (c *Ceil) String() string {
return fmt.Sprintf("CEIL(%s)", c.Child)
}

// TransformUp implements the Expression interface.
func (c *Ceil) TransformUp(fn sql.TransformExprFunc) (sql.Expression, error) {
child, err := c.Child.TransformUp(fn)
if err != nil {
return nil, err
}
return fn(NewArrayLength(child))
}

// Eval implements the Expression interface.
func (c *Ceil) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
if !sql.IsNumber(c.Child.Type()) {
return nil, sql.ErrInvalidType.New(c.Child.Type().Type().String())
}

child, err := c.Child.Eval(ctx, row)

if !sql.IsDecimal(c.Child.Type()) {
return child, err
}

if err != nil {
return nil, err
}

if child == nil {
return nil, nil
}

switch num := child.(type) {
case float64:
return math.Ceil(num), nil
case float32:
return float32(math.Ceil(float64(num))), nil
default:
return nil, sql.ErrInvalidType.New(reflect.TypeOf(num))
}
}

// Floor returns the biggest integer value not less than X.
type Floor struct {
expression.UnaryExpression
}

func (f *Floor) Resolved() bool {
return f.Child.Resolved()
}

func (f *Floor) IsNullable() bool {
return f.Child.IsNullable()
}

func (f *Floor) Children() []sql.Expression {
return f.Child.Children()
}

func NewFloor(array sql.Expression) sql.Expression {
return &Floor{expression.UnaryExpression{Child: array}}
}

func (f *Floor) Type() sql.Type {
return f.Child.Type()
}

func (f *Floor) String() string {
return fmt.Sprintf("FLOOR(%s)", f.Child)
}

// TransformUp implements the Expression interface.
func (f *Floor) TransformUp(fn sql.TransformExprFunc) (sql.Expression, error) {
child, err := f.Child.TransformUp(fn)
if err != nil {
return nil, err
}
return fn(NewArrayLength(child))
}

// Eval implements the Expression interface.
func (f *Floor) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
if !sql.IsNumber(f.Child.Type()) {
return nil, sql.ErrInvalidType.New(f.Child.Type().Type().String())
}

child, err := f.Child.Eval(ctx, row)

if !sql.IsDecimal(f.Child.Type()) {
return child, err
}

if err != nil {
return nil, err
}

if child == nil {
return nil, nil
}

switch num := child.(type) {
case float64:
return math.Floor(num), nil
case float32:
return float32(math.Floor(float64(num))), nil
default:
return nil, sql.ErrInvalidType.New(reflect.TypeOf(num))
}
}
Loading

0 comments on commit 865b69a

Please sign in to comment.