Commit bb2f4b81 authored by unknown's avatar unknown
Browse files

Merge mysql.com:/home/jimw/my/mysql-5.0-13534

into  mysql.com:/home/jimw/my/mysql-5.0-clean

parents f4e4f846 e84f7939
Loading
Loading
Loading
Loading
+51 −0
Original line number Diff line number Diff line
@@ -760,3 +760,54 @@ call t_sysdate();
@a != @b
1
drop procedure t_sysdate;
select timestampdiff(month,'2004-09-11','2004-09-11');
timestampdiff(month,'2004-09-11','2004-09-11')
0
select timestampdiff(month,'2004-09-11','2005-09-11');
timestampdiff(month,'2004-09-11','2005-09-11')
12
select timestampdiff(month,'2004-09-11','2006-09-11');
timestampdiff(month,'2004-09-11','2006-09-11')
24
select timestampdiff(month,'2004-09-11','2007-09-11');
timestampdiff(month,'2004-09-11','2007-09-11')
36
select timestampdiff(month,'2005-09-11','2004-09-11');
timestampdiff(month,'2005-09-11','2004-09-11')
-12
select timestampdiff(month,'2005-09-11','2003-09-11');
timestampdiff(month,'2005-09-11','2003-09-11')
-24
select timestampdiff(month,'2004-02-28','2005-02-28');
timestampdiff(month,'2004-02-28','2005-02-28')
12
select timestampdiff(month,'2004-02-29','2005-02-28');
timestampdiff(month,'2004-02-29','2005-02-28')
11
select timestampdiff(month,'2004-02-28','2005-02-28');
timestampdiff(month,'2004-02-28','2005-02-28')
12
select timestampdiff(month,'2004-03-29','2005-03-28');
timestampdiff(month,'2004-03-29','2005-03-28')
11
select timestampdiff(month,'2003-02-28','2004-02-29');
timestampdiff(month,'2003-02-28','2004-02-29')
12
select timestampdiff(month,'2003-02-28','2005-02-28');
timestampdiff(month,'2003-02-28','2005-02-28')
24
select timestampdiff(month,'1999-09-11','2001-10-10');
timestampdiff(month,'1999-09-11','2001-10-10')
24
select timestampdiff(month,'1999-09-11','2001-9-11');
timestampdiff(month,'1999-09-11','2001-9-11')
24
select timestampdiff(year,'1999-09-11','2001-9-11');
timestampdiff(year,'1999-09-11','2001-9-11')
2
select timestampdiff(year,'2004-02-28','2005-02-28');
timestampdiff(year,'2004-02-28','2005-02-28')
1
select timestampdiff(year,'2004-02-29','2005-02-28');
timestampdiff(year,'2004-02-29','2005-02-28')
0
+24 −0
Original line number Diff line number Diff line
@@ -404,4 +404,28 @@ delimiter ;//
call t_sysdate();
drop procedure t_sysdate;

#
# Bug #13534: timestampdiff() returned incorrect results across leap years
#
select timestampdiff(month,'2004-09-11','2004-09-11');
select timestampdiff(month,'2004-09-11','2005-09-11');
select timestampdiff(month,'2004-09-11','2006-09-11');
select timestampdiff(month,'2004-09-11','2007-09-11');
select timestampdiff(month,'2005-09-11','2004-09-11');
select timestampdiff(month,'2005-09-11','2003-09-11');

select timestampdiff(month,'2004-02-28','2005-02-28');
select timestampdiff(month,'2004-02-29','2005-02-28');
select timestampdiff(month,'2004-02-28','2005-02-28');
select timestampdiff(month,'2004-03-29','2005-03-28');
select timestampdiff(month,'2003-02-28','2004-02-29');
select timestampdiff(month,'2003-02-28','2005-02-28');

select timestampdiff(month,'1999-09-11','2001-10-10');
select timestampdiff(month,'1999-09-11','2001-9-11');

select timestampdiff(year,'1999-09-11','2001-9-11');
select timestampdiff(year,'2004-02-28','2005-02-28');
select timestampdiff(year,'2004-02-29','2005-02-28');

# End of 5.0 tests
+21 −42
Original line number Diff line number Diff line
@@ -2723,16 +2723,16 @@ longlong Item_func_timestamp_diff::val_int()
      int_type == INTERVAL_QUARTER ||
      int_type == INTERVAL_MONTH)
  {
    uint year;
    uint year_beg, year_end, month_beg, month_end;
    uint diff_days= (uint) (seconds/86400L);
    uint diff_years= 0;
    uint year_beg, year_end, month_beg, month_end, day_beg, day_end;
    uint years= 0;
    if (neg == -1)
    {
      year_beg= ltime2.year;
      year_end= ltime1.year;
      month_beg= ltime2.month;
      month_end= ltime1.month;
      day_beg= ltime2.day;
      day_end= ltime1.day;
    }
    else
    {
@@ -2740,53 +2740,32 @@ longlong Item_func_timestamp_diff::val_int()
      year_end= ltime2.year;
      month_beg= ltime1.month;
      month_end= ltime2.month;
      day_beg= ltime1.day;
      day_end= ltime2.day;
    }
    /* calc years*/
    for (year= year_beg;year < year_end; year++)
    {
      uint days=calc_days_in_year(year);
      if (days > diff_days)
	break;
      diff_days-= days;
      diff_years++;
    }

    /* calc months;  Current year is in the 'year' variable */
    month_beg--;	/* Change months to be 0-11 for easier calculation */
    month_end--;

    months= 12*diff_years;
    while (month_beg != month_end)
    {
      uint m_days= (uint) days_in_month[month_beg];
      if (month_beg == 1)
      {
	/* This is only calculated once so there is no reason to cache it*/
	uint leap= (uint) ((year & 3) == 0 && (year%100 ||
					       (year%400 == 0 && year)));
	m_days+= leap;
      }
      if (m_days > diff_days)
	break;
      diff_days-= m_days;
      months++;
      if (month_beg++ == 11)		/* if we wrap to next year */
      {
	month_beg= 0;
	year++;
      }
    }
    if (neg == -1)
      months= -months;
    /* calc years */
    years= year_end - year_beg;
    if (month_end < month_beg || (month_end == month_beg && day_end < day_beg))
      years-= 1;

    /* calc months */
    months= 12*years;
    if (month_end < month_beg || (month_end == month_beg && day_end < day_beg))
      months+= 12 - (month_beg - month_end);
    else
      months+= (month_end - month_beg);
    if (day_end < day_beg)
      months-= 1;
  }

  switch (int_type) {
  case INTERVAL_YEAR:
    return months/12;
    return months/12*neg;
  case INTERVAL_QUARTER:
    return months/3;
    return months/3*neg;
  case INTERVAL_MONTH:
    return months;
    return months*neg;
  case INTERVAL_WEEK:          
    return seconds/86400L/7L*neg;
  case INTERVAL_DAY: