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  }