diff --git a/Makefile.am b/Makefile.am index 403a4ba2137..401a53459ae 100644 --- a/Makefile.am +++ b/Makefile.am @@ -97,36 +97,35 @@ tags: support-files/build-tags .PHONY: init-db bin-dist -# Test installation. Ports are configurable from the environment. - -MYSQL_TEST_MANAGER_PORT = 9305 -MYSQL_TEST_MASTER_PORT = 9306 -MYSQL_TEST_SLAVE_PORT = 9308 -MYSQL_TEST_NDB_PORT = 9350 -MYSQL_TEST_RUN_ARGS = --manager-port=$(MYSQL_TEST_MANAGER_PORT) \ - --master_port=$(MYSQL_TEST_MASTER_PORT) \ - --slave_port=$(MYSQL_TEST_SLAVE_PORT) \ - --ndbcluster_port=$(MYSQL_TEST_NDB_PORT) +# Target 'test' will run the regression test suite using the built server. +# +# If you are running in a shared environment, users can avoid clashing +# port numbers by setting individual small numbers 1-100 to the +# environment variable MTR_BUILD_THREAD. The script "mysql-test-run" +# will then calculate the various port numbers it needs from this, +# making sure each user use different ports. test: cd mysql-test ; \ - ./mysql-test-run $(MYSQL_TEST_RUN_ARGS) && \ - ./mysql-test-run $(MYSQL_TEST_RUN_ARGS) --ps-protocol + ./mysql-test-run && \ + ./mysql-test-run --ps-protocol test-force: - cd mysql-test ; \ - ./mysql-test-run $(MYSQL_TEST_RUN_ARGS) --force ; \ - ./mysql-test-run $(MYSQL_TEST_RUN_ARGS) --ps-protocol --force + cd mysql-test; \ + ./mysql-test-run --force ; \ + ./mysql-test-run --ps-protocol --force +# We are testing a new Perl version of the test script test-pl: - cd mysql-test ; \ - ./mysql-test-run.pl $(MYSQL_TEST_RUN_ARGS) && \ - ./mysql-test-run.pl $(MYSQL_TEST_RUN_ARGS) --ps-protocol + cd mysql-test; \ + ./mysql-test-run.pl && \ + ./mysql-test-run.pl --ps-protocol test-force-pl: - cd mysql-test ; \ - ./mysql-test-run.pl $(MYSQL_TEST_RUN_ARGS) --force ; \ - ./mysql-test-run.pl $(MYSQL_TEST_RUN_ARGS) --ps-protocol --force + cd mysql-test; \ + ./mysql-test-run.pl --force ; \ + ./mysql-test-run.pl --ps-protocol --force # Don't update the files from bitkeeper %::SCCS/s.% + diff --git a/include/my_pthread.h b/include/my_pthread.h index 3d9056541d7..ee2c801ff6e 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -25,10 +25,10 @@ #endif #ifdef __cplusplus -#define EXTERN_C extern "C" +#define EXTERNC extern "C" extern "C" { #else -#define EXTERN_C +#define EXTERNC #endif /* __cplusplus */ #if defined(__WIN__) || defined(OS2) @@ -80,10 +80,10 @@ struct timespec { /* For pthread_cond_timedwait() */ typedef int pthread_mutexattr_t; #define win_pthread_self my_thread_var->pthread_self #ifdef OS2 -#define pthread_handler_t EXTERN_C void * _Optlink +#define pthread_handler_t EXTERNC void * _Optlink typedef void * (_Optlink *pthread_handler)(void *); #else -#define pthread_handler_t EXTERN_C void * __cdecl +#define pthread_handler_t EXTERNC void * __cdecl typedef void * (__cdecl *pthread_handler)(void *); #endif @@ -187,7 +187,7 @@ typedef int pthread_attr_t; /* Needed by Unixware 7.0.0 */ #define pthread_key_create(A,B) thr_keycreate((A),(B)) #define pthread_key_delete(A) thr_keydelete(A) -#define pthread_handler_t EXTERN_C void * +#define pthread_handler_t EXTERNC void * #define pthread_key(T,V) pthread_key_t V void * my_pthread_getspecific_imp(pthread_key_t key); @@ -265,7 +265,7 @@ extern int my_pthread_getprio(pthread_t thread_id); #define my_pthread_getspecific_ptr(T,V) my_pthread_getspecific(T,(V)) #define my_pthread_setspecific_ptr(T,V) pthread_setspecific(T,(void*) (V)) #define pthread_detach_this_thread() -#define pthread_handler_t EXTERN_C void * +#define pthread_handler_t EXTERNC void * typedef void *(* pthread_handler)(void *); /* Test first for RTS or FSU threads */ diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index a4f8f2ac1f9..e2d5dde79e5 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -216,6 +216,25 @@ NDBCLUSTER_PORT=9350 MYSQL_MANAGER_PW_FILE=$MYSQL_TEST_DIR/var/tmp/manager.pwd MYSQL_MANAGER_LOG=$MYSQL_TEST_DIR/var/log/manager.log MYSQL_MANAGER_USER=root + +# +# To make it easier for different devs to work on the same host, +# an environment variable can be used to control all ports. A small +# number is to be used, 0 - 16 or similar. +# +if [ -n "$MTR_BUILD_THREAD" ] ; then + MASTER_MYPORT=`expr $MTR_BUILD_THREAD '*' 40 + 8120` + MYSQL_MANAGER_PORT=`expr $MASTER_MYPORT + 2` + SLAVE_MYPORT=`expr $MASTER_MYPORT + 16` + NDBCLUSTER_PORT=`expr $MASTER_MYPORT + 24` + + echo "Using MTR_BUILD_THREAD = $MTR_BUILD_THREAD" + echo "Using MASTER_MYPORT = $MASTER_MYPORT" + echo "Using MYSQL_MANAGER_PORT = $MYSQL_MANAGER_PORT" + echo "Using SLAVE_MYPORT = $SLAVE_MYPORT" + echo "Using NDBCLUSTER_PORT = $NDBCLUSTER_PORT" +fi + NO_SLAVE=0 USER_TEST= FAILED_CASES= diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 9275a893309..64dafa132b4 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -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 diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 3dd7f7276fb..3a2eea59bed 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -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 diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 7f94c19647e..459b5a22cb1 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -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; - } - /* 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++; + day_beg= ltime1.day; + day_end= ltime2.day; } - /* calc months; Current year is in the 'year' variable */ - month_beg--; /* Change months to be 0-11 for easier calculation */ - month_end--; + /* calc years */ + years= year_end - year_beg; + if (month_end < month_beg || (month_end == month_beg && day_end < day_beg)) + years-= 1; - 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 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: diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 1d1649edc94..252fb9c8467 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -7155,6 +7155,7 @@ static void fix_paths(void) CHARSET_DIR, NullS); } (void) my_load_path(mysql_charsets_dir, mysql_charsets_dir, buff); + convert_dirname(mysql_charsets_dir, mysql_charsets_dir, NullS); charsets_dir=mysql_charsets_dir; if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir))