Example #1
0
File: frpg.c Project: haipome/bin
char get_all()
{
	int i = get_rand(87);
	if (i < 62)
		return get_letter_digit();
	else
		return get_punct();
}
my_bool
str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time,
                ulonglong flags, MYSQL_TIME_STATUS *status)
{
  const char *end=str+length, *pos;
  uint number_of_fields= 0, digits, year_length, not_zero_date;
  DBUG_ENTER("str_to_datetime");
  bzero(l_time, sizeof(*l_time));

  if (flags & TIME_TIME_ONLY)
  {
    my_bool ret= str_to_time(str, length, l_time, flags, status);
    DBUG_RETURN(ret);
  }

  my_time_status_init(status);

  /* Skip space at start */
  for (; str != end && my_isspace(&my_charset_latin1, *str) ; str++)
    ;
  if (str == end || ! my_isdigit(&my_charset_latin1, *str))
  {
    status->warnings= MYSQL_TIME_WARN_TRUNCATED;
    l_time->time_type= MYSQL_TIMESTAMP_NONE;
    DBUG_RETURN(1);
  }

  /*
    Calculate number of digits in first part.
    If length= 8 or >= 14 then year is of format YYYY.
    (YYYY-MM-DD,  YYYYMMDD, YYYYYMMDDHHMMSS)
  */
  pos= str;
  digits= skip_digits(&pos, end);

  if (pos < end && *pos == 'T') /* YYYYYMMDDHHMMSSThhmmss is supported too */
  {
    pos++;
    digits+= skip_digits(&pos, end);
  }
  if (pos < end && *pos == '.' && digits >= 12) /* YYYYYMMDDHHMMSShhmmss.uuuuuu is supported too */
  {
    pos++;
    skip_digits(&pos, end); // ignore the return value
  }

  if (pos == end)
  {
    /*
      Found date in internal format
      (only numbers like [YY]YYMMDD[T][hhmmss[.uuuuuu]])
    */
    year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2;
    if (get_digits(&l_time->year, &number_of_fields, &str, end, year_length) 
        || get_digits(&l_time->month, &number_of_fields, &str, end, 2)
        || get_digits(&l_time->day, &number_of_fields, &str, end, 2)
        || get_maybe_T(&str, end)
        || get_digits(&l_time->hour, &number_of_fields, &str, end, 2)
        || get_digits(&l_time->minute, &number_of_fields, &str, end, 2)
        || get_digits(&l_time->second, &number_of_fields, &str, end, 2))
     status->warnings|= MYSQL_TIME_WARN_TRUNCATED;
  }
  else
  {
    const char *start= str;
    if (get_number(&l_time->year, &number_of_fields, &str, end))
      status->warnings|= MYSQL_TIME_WARN_TRUNCATED;
    year_length= str - start;

    if (!status->warnings &&
        (get_punct(&str, end)
         || get_number(&l_time->month, &number_of_fields, &str, end)
         || get_punct(&str, end)
         || get_number(&l_time->day, &number_of_fields, &str, end)
         || get_date_time_separator(&number_of_fields, flags, &str, end)
         || get_number(&l_time->hour, &number_of_fields, &str, end)
         || get_punct(&str, end)
         || get_number(&l_time->minute, &number_of_fields, &str, end)
         || get_punct(&str, end)
         || get_number(&l_time->second, &number_of_fields, &str, end)))
      status->warnings|= MYSQL_TIME_WARN_TRUNCATED;
  }

  /* we're ok if date part is correct. even if the rest is truncated */
  if (number_of_fields < 3)
  {
    l_time->time_type= MYSQL_TIMESTAMP_NONE;
    status->warnings|= MYSQL_TIME_WARN_TRUNCATED;
    DBUG_RETURN(TRUE);
  }

  if (!status->warnings && str < end && *str == '.')
  {
    str++;
    get_microseconds(&l_time->second_part, status,
                     &number_of_fields, &str, end);
  }

  not_zero_date = l_time->year || l_time->month || l_time->day ||
                  l_time->hour || l_time->minute || l_time->second ||
                  l_time->second_part;

  if (year_length == 2 && not_zero_date)
    l_time->year+= (l_time->year < YY_PART_YEAR ? 2000 : 1900);

  if (l_time->year > 9999 || l_time->month > 12 || l_time->day > 31 ||
      l_time->hour > 23 || l_time->minute > 59 || l_time->second > 59)
  {
    status->warnings|= MYSQL_TIME_WARN_TRUNCATED;
    goto err;
  }

  if (check_date(l_time, not_zero_date, flags, &status->warnings))
    goto err;

  l_time->time_type= (number_of_fields <= 3 ?
                      MYSQL_TIMESTAMP_DATE : MYSQL_TIMESTAMP_DATETIME);

  for (; str != end ; str++)
  {
    if (!my_isspace(&my_charset_latin1,*str))
    {
      status->warnings= MYSQL_TIME_WARN_TRUNCATED;
      break;
    }
  }

  DBUG_RETURN(FALSE);

err:
  bzero((char*) l_time, sizeof(*l_time));
  l_time->time_type= MYSQL_TIMESTAMP_ERROR;
  DBUG_RETURN(TRUE);
}