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

Commit 6a63b82

Browse files
authored
Merge branch 'master' into base64-functions
2 parents ee0bce0 + 87f17d6 commit 6a63b82

File tree

6 files changed

+124
-1
lines changed

6 files changed

+124
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ We support and actively test against certain third-party clients to ensure compa
9898
|`RPAD(str, len, padstr)`|Returns the string str, right-padded with the string padstr to a length of len characters.|
9999
|`RTRIM(str)`|Returns the string str with trailing space characters removed.|
100100
|`SECOND(date)`|Returns the seconds of the given date.|
101+
|`SLEEP(seconds)`|Wait for the specified number of seconds (can be fractional).|
101102
|`SOUNDEX(str)`|Returns the soundex of a string.|
102103
|`SPLIT(str,sep)`|Receives a string and a separator and returns the parts of the string split by the separator as a JSON array of strings.|
103104
|`SQRT(X)`|Returns the square root of a nonnegative number X.|

SUPPORTED.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
- LOG10
112112
- TO_BASE64
113113
- FROM_BASE64
114+
- SLEEP
114115

115116
## Time functions
116117
- DAY

engine_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,11 @@ var queries = []struct {
883883
},
884884
{
885885
"SELECT FROM_BASE64('YmFy')",
886-
[]sql.Row{{string("bar")}},
886+
[]sql.Row{{string("bar")}
887+
},
888+
{
889+
"SELECT SLEEP(0.5)",
890+
[]sql.Row{{int(0)}},
887891
},
888892
}
889893

sql/expression/function/registry.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,5 @@ var Defaults = []sql.Function{
7676
sql.Function0{Name: "now", Fn: NewNow},
7777
sql.Function1{Name: "to_base64", Fn: NewToBase64},
7878
sql.Function1{Name: "from_base64", Fn: NewFromBase64},
79+
sql.Function1{Name: "sleep", Fn: NewSleep},
7980
}

sql/expression/function/sleep.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package function
2+
3+
import (
4+
"fmt"
5+
"time"
6+
7+
"gopkg.in/src-d/go-mysql-server.v0/sql"
8+
"gopkg.in/src-d/go-mysql-server.v0/sql/expression"
9+
)
10+
11+
// Sleep is a function that just waits for the specified number of seconds
12+
// and returns 0.
13+
// It can be useful to test timeouts or long queries.
14+
type Sleep struct {
15+
expression.UnaryExpression
16+
}
17+
18+
// NewSleep creates a new Sleep expression.
19+
func NewSleep(e sql.Expression) sql.Expression {
20+
return &Sleep{expression.UnaryExpression{Child: e}}
21+
}
22+
23+
// Eval implements the Expression interface.
24+
func (s *Sleep) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
25+
child, err := s.Child.Eval(ctx, row)
26+
27+
if err != nil {
28+
return nil, err
29+
}
30+
31+
if child == nil {
32+
return nil, nil
33+
}
34+
35+
child, err = sql.Float64.Convert(child)
36+
if err != nil {
37+
return nil, err
38+
}
39+
40+
time.Sleep(time.Duration(child.(float64) * 1000) * time.Millisecond)
41+
return 0, nil
42+
}
43+
44+
// String implements the Stringer interface.
45+
func (s *Sleep) String() string {
46+
return fmt.Sprintf("SLEEP(%s)", s.Child)
47+
}
48+
49+
// IsNullable implements the Expression interface.
50+
func (s *Sleep) IsNullable() bool {
51+
return false
52+
}
53+
54+
// TransformUp implements the Expression interface.
55+
func (s *Sleep) TransformUp(f sql.TransformExprFunc) (sql.Expression, error) {
56+
child, err := s.Child.TransformUp(f)
57+
if err != nil {
58+
return nil, err
59+
}
60+
return f(NewSleep(child))
61+
}
62+
63+
// Type implements the Expression interface.
64+
func (s *Sleep) Type() sql.Type {
65+
return sql.Int32
66+
}

sql/expression/function/sleep_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package function
2+
3+
import (
4+
"testing"
5+
"time"
6+
7+
"github.com/stretchr/testify/require"
8+
"gopkg.in/src-d/go-mysql-server.v0/sql"
9+
"gopkg.in/src-d/go-mysql-server.v0/sql/expression"
10+
)
11+
12+
func TestSleep(t *testing.T) {
13+
f := NewSleep(
14+
expression.NewGetField(0, sql.Text, "n", false),
15+
)
16+
testCases := []struct {
17+
name string
18+
row sql.Row
19+
expected interface{}
20+
waitTime float64
21+
err bool
22+
}{
23+
{"null input", sql.NewRow(nil), nil, 0, false},
24+
{"string input", sql.NewRow("foo"), nil, 0, true},
25+
{"int input", sql.NewRow(3), int(0), 3.0, false},
26+
{"number is zero", sql.NewRow(0), int(0), 0, false},
27+
{"negative number", sql.NewRow(-4), int(0), 0, false},
28+
{"positive number", sql.NewRow(4.48), int(0), 4.48, false},
29+
}
30+
for _, tt := range testCases {
31+
t.Run(tt.name, func(t *testing.T) {
32+
t.Helper()
33+
require := require.New(t)
34+
ctx := sql.NewEmptyContext()
35+
36+
t1 := time.Now()
37+
v, err := f.Eval(ctx, tt.row)
38+
t2 := time.Now()
39+
if tt.err {
40+
require.Error(err)
41+
} else {
42+
require.NoError(err)
43+
require.Equal(tt.expected, v)
44+
45+
waited := t2.Sub(t1).Seconds()
46+
require.InDelta(waited, tt.waitTime, 0.1)
47+
}
48+
})
49+
}
50+
}

0 commit comments

Comments
 (0)