github.com/dolthub/go-mysql-server@v0.18.0/sql/expression/function/sleep.go (about) 1 // Copyright 2020-2021 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package function 16 17 import ( 18 "context" 19 "fmt" 20 "time" 21 22 "github.com/dolthub/go-mysql-server/sql" 23 "github.com/dolthub/go-mysql-server/sql/expression" 24 "github.com/dolthub/go-mysql-server/sql/types" 25 ) 26 27 // Sleep is a function that just waits for the specified number of seconds 28 // and returns 0. 29 // It can be useful to test timeouts or long queries. 30 type Sleep struct { 31 expression.UnaryExpression 32 } 33 34 var _ sql.FunctionExpression = (*Sleep)(nil) 35 var _ sql.CollationCoercible = (*Sleep)(nil) 36 37 // NewSleep creates a new Sleep expression. 38 func NewSleep(e sql.Expression) sql.Expression { 39 return &Sleep{expression.UnaryExpression{Child: e}} 40 } 41 42 // FunctionName implements sql.FunctionExpression 43 func (s *Sleep) FunctionName() string { 44 return "sleep" 45 } 46 47 // Description implements sql.FunctionExpression 48 func (s *Sleep) Description() string { 49 return "waits for the specified number of seconds (can be fractional)." 50 } 51 52 // Eval implements the Expression interface. 53 func (s *Sleep) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) { 54 child, err := s.Child.Eval(ctx, row) 55 56 if err != nil { 57 return nil, err 58 } 59 60 if child == nil { 61 return nil, nil 62 } 63 64 child, _, err = types.Float64.Convert(child) 65 if err != nil { 66 return nil, err 67 } 68 69 t := time.NewTimer(time.Duration(child.(float64)*1000) * time.Millisecond) 70 defer t.Stop() 71 72 select { 73 case <-ctx.Done(): 74 return 0, context.Canceled 75 case <-t.C: 76 return 0, nil 77 } 78 } 79 80 // String implements the fmt.Stringer interface. 81 func (s *Sleep) String() string { 82 return fmt.Sprintf("%s(%s)", s.FunctionName(), s.Child) 83 } 84 85 // IsNullable implements the Expression interface. 86 func (s *Sleep) IsNullable() bool { 87 return false 88 } 89 90 // WithChildren implements the Expression interface. 91 func (s *Sleep) WithChildren(children ...sql.Expression) (sql.Expression, error) { 92 if len(children) != 1 { 93 return nil, sql.ErrInvalidChildrenNumber.New(s, len(children), 1) 94 } 95 return NewSleep(children[0]), nil 96 } 97 98 // Type implements the Expression interface. 99 func (s *Sleep) Type() sql.Type { 100 return types.Int32 101 } 102 103 // CollationCoercibility implements the interface sql.CollationCoercible. 104 func (*Sleep) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 105 return sql.Collation_binary, 5 106 }