github.com/dolthub/go-mysql-server@v0.18.0/sql/expression/function/str_to_date.go (about) 1 package function 2 3 import ( 4 "fmt" 5 6 "github.com/dolthub/go-mysql-server/sql/planbuilder/dateparse" 7 8 "github.com/dolthub/go-mysql-server/sql" 9 "github.com/dolthub/go-mysql-server/sql/types" 10 ) 11 12 // NewStrToDate constructs a new function expression from the given child expressions. 13 func NewStrToDate(args ...sql.Expression) (sql.Expression, error) { 14 if len(args) != 2 { 15 return nil, sql.ErrInvalidArgumentNumber.New("STR_TO_DATE", 2, len(args)) 16 } 17 return &StrToDate{ 18 Date: args[0], 19 Format: args[1], 20 }, nil 21 } 22 23 // StrToDate defines the built-in function STR_TO_DATE(str, format) 24 type StrToDate struct { 25 Date sql.Expression 26 Format sql.Expression 27 } 28 29 var _ sql.FunctionExpression = (*StrToDate)(nil) 30 var _ sql.CollationCoercible = (*StrToDate)(nil) 31 32 // Description implements sql.FunctionExpression 33 func (s StrToDate) Description() string { 34 return "parses the date/datetime/timestamp expression according to the format specifier." 35 } 36 37 // Resolved returns whether the node is resolved. 38 func (s StrToDate) Resolved() bool { 39 dateResolved := s.Date == nil || s.Date.Resolved() 40 formatResolved := s.Format == nil || s.Format.Resolved() 41 return dateResolved && formatResolved 42 } 43 44 func (s StrToDate) String() string { 45 return fmt.Sprintf("%s(%s,%s)", s.FunctionName(), s.Date, s.Format) 46 } 47 48 // Type returns the expression type. 49 func (s StrToDate) Type() sql.Type { 50 // TODO: precision 51 return types.Datetime 52 } 53 54 // CollationCoercibility implements the interface sql.CollationCoercible. 55 func (StrToDate) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) { 56 return sql.Collation_binary, 5 57 } 58 59 // IsNullable returns whether the expression can be null. 60 func (s StrToDate) IsNullable() bool { 61 return true 62 } 63 64 // Eval evaluates the given row and returns a result. 65 func (s StrToDate) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) { 66 date, err := s.Date.Eval(ctx, row) 67 if err != nil { 68 return nil, err 69 } 70 format, err := s.Format.Eval(ctx, row) 71 if err != nil { 72 return nil, err 73 } 74 75 dateStr, ok := date.(string) 76 if !ok { 77 // TODO: improve this error 78 return nil, sql.ErrInvalidType.New(fmt.Sprintf("%T", date)) 79 } 80 formatStr, ok := format.(string) 81 if !ok { 82 // TODO: improve this error 83 return nil, sql.ErrInvalidType.New(fmt.Sprintf("%T", formatStr)) 84 } 85 86 goTime, err := dateparse.ParseDateWithFormat(dateStr, formatStr) 87 if err != nil { 88 ctx.Warn(1411, fmt.Sprintf("Incorrect value: '%s' for function %s", dateStr, s.FunctionName())) 89 return nil, nil 90 } 91 92 // zero dates '0000-00-00' and '2010-00-13' are allowed, 93 // but depends on strict sql_mode with NO_ZERO_DATE or NO_ZERO_IN_DATE modes enabled. 94 return goTime, nil 95 } 96 97 // Children returns the children expressions of this expression. 98 func (s StrToDate) Children() []sql.Expression { 99 children := make([]sql.Expression, 0, 2) 100 if s.Date != nil { 101 children = append(children, s.Date) 102 } 103 if s.Format != nil { 104 children = append(children, s.Format) 105 } 106 return children 107 } 108 109 func (s StrToDate) WithChildren(children ...sql.Expression) (sql.Expression, error) { 110 return NewStrToDate(children...) 111 } 112 113 func (s StrToDate) FunctionName() string { 114 return "str_to_date" 115 }