code: func (b *builtinGreatestTimeSig) evalString(row chunk.Row) (_ string, isNull bool, err error) {
  	var (
  		v string
  		t types.Time
  	)
  	max := types.ZeroDatetime
  	sc := b.ctx.GetSessionVars().StmtCtx
  	for i := 0; i < len(b.args); i++ {
  		v, isNull, err = b.args[i].EvalString(b.ctx, row)
  		if isNull || err != nil {
  			return "", true, err
  		}
  		t, err = types.ParseDatetime(sc, v)
  		if err != nil {
  			if err = handleInvalidTimeError(b.ctx, err); err != nil {
  				return v, true, err
  			}
  			continue
  		}
  		if t.Compare(max) > 0 {
  			max = t
  		}
  	}
  	return max.String(), false, nil
  }
docs: // evalString evals a builtinGreatestTimeSig.
  // See http://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_greatest