From 82d127b55bbbeaf7fa263122365143f7727b7f10 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 27 Jun 2006 19:33:59 +0400 Subject: [PATCH 1/3] Dec. 31st, 9999 is still a valid date, only starting with Jan 1st 10000 things become invalid (Bug #12356) mysql-test/r/func_sapdb.result: test cases for date range edge cases added mysql-test/r/func_time.result: test cases for date range edge cases added mysql-test/t/func_sapdb.test: test cases for date range edge cases added mysql-test/t/func_time.test: test cases for date range edge cases added --- mysql-test/r/func_sapdb.result | 6 ++++++ mysql-test/r/func_time.result | 6 ++++++ mysql-test/t/func_sapdb.test | 2 ++ mysql-test/t/func_time.test | 6 ++++++ sql/item_timefunc.cc | 11 ++++++----- 5 files changed, 26 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/func_sapdb.result b/mysql-test/r/func_sapdb.result index ea40e1559fd..b18885e218a 100644 --- a/mysql-test/r/func_sapdb.result +++ b/mysql-test/r/func_sapdb.result @@ -71,6 +71,12 @@ makedate(1997,1) select makedate(1997,0); makedate(1997,0) NULL +select makedate(9999,365); +makedate(9999,365) +9999-12-31 +select makedate(9999,366); +makedate(9999,366) +NULL select addtime("1997-12-31 23:59:59.999999", "1 1:1:1.000002"); addtime("1997-12-31 23:59:59.999999", "1 1:1:1.000002") 1998-01-02 01:01:01.000001 diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index c90a4258036..fab0bf01f58 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -352,6 +352,12 @@ extract(SECOND FROM "1999-01-02 10:11:12") select extract(MONTH FROM "2001-02-00"); extract(MONTH FROM "2001-02-00") 2 +SELECT DATE_SUB(str_to_date('9999-12-31 00:01:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE); +DATE_SUB(str_to_date('9999-12-31 00:01:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE) +9999-12-31 00:00:00 +SELECT DATE_ADD(str_to_date('9999-12-30 23:59:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE); +DATE_ADD(str_to_date('9999-12-30 23:59:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE) +9999-12-31 00:00:00 SELECT "1900-01-01 00:00:00" + INTERVAL 2147483648 SECOND; "1900-01-01 00:00:00" + INTERVAL 2147483648 SECOND 1968-01-20 03:14:08 diff --git a/mysql-test/t/func_sapdb.test b/mysql-test/t/func_sapdb.test index 8fd793f067b..930ad37c60c 100644 --- a/mysql-test/t/func_sapdb.test +++ b/mysql-test/t/func_sapdb.test @@ -37,6 +37,8 @@ select weekofyear("1997-11-31 23:59:59.000001"); select makedate(1997,1); select makedate(1997,0); +select makedate(9999,365); +select makedate(9999,366); #Time functions diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index d69545712c8..b232fb14e1e 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -139,6 +139,12 @@ select extract(MINUTE_SECOND FROM "10:11:12"); select extract(SECOND FROM "1999-01-02 10:11:12"); select extract(MONTH FROM "2001-02-00"); +# +# MySQL Bugs: #12356: DATE_SUB or DATE_ADD incorrectly returns null +# +SELECT DATE_SUB(str_to_date('9999-12-31 00:01:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE); +SELECT DATE_ADD(str_to_date('9999-12-30 23:59:00','%Y-%m-%d %H:%i:%s'), INTERVAL 1 MINUTE); + # # Test big intervals (Bug #3498) # diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 8d3e768b74e..27876096bc5 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -27,6 +27,7 @@ /* TODO: Move month and days to language files */ +/* Day number for Dec 31st, 9999 */ #define MAX_DAY_NUMBER 3652424L static const char *month_names[]= @@ -401,7 +402,7 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, if (yearday > 0) { uint days= calc_daynr(l_time->year,1,1) + yearday - 1; - if (days <= 0 || days >= MAX_DAY_NUMBER) + if (days <= 0 || days > MAX_DAY_NUMBER) goto err; get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day); } @@ -447,7 +448,7 @@ static bool extract_date_time(DATE_TIME_FORMAT *format, (weekday - 1); } - if (days <= 0 || days >= MAX_DAY_NUMBER) + if (days <= 0 || days > MAX_DAY_NUMBER) goto err; get_date_from_daynr(days,&l_time->year,&l_time->month,&l_time->day); } @@ -1931,7 +1932,7 @@ bool Item_date_add_interval::get_date(TIME *ltime, uint fuzzy_date) ltime->hour= (uint) (sec/3600); daynr= calc_daynr(ltime->year,ltime->month,1) + days; /* Day number from year 0 to 9999-12-31 */ - if ((ulonglong) daynr >= MAX_DAY_NUMBER) + if ((ulonglong) daynr > MAX_DAY_NUMBER) goto null_date; get_date_from_daynr((long) daynr, <ime->year, <ime->month, <ime->day); @@ -1941,7 +1942,7 @@ bool Item_date_add_interval::get_date(TIME *ltime, uint fuzzy_date) period= (calc_daynr(ltime->year,ltime->month,ltime->day) + sign * (long) interval.day); /* Daynumber from year 0 to 9999-12-31 */ - if ((ulong) period >= MAX_DAY_NUMBER) + if ((ulong) period > MAX_DAY_NUMBER) goto null_date; get_date_from_daynr((long) period,<ime->year,<ime->month,<ime->day); break; @@ -2412,7 +2413,7 @@ String *Item_func_makedate::val_str(String *str) days= calc_daynr(yearnr,1,1) + daynr - 1; /* Day number from year 0 to 9999-12-31 */ - if (days >= 0 && days < MAX_DAY_NUMBER) + if (days >= 0 && days <= MAX_DAY_NUMBER) { null_value=0; get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day); From f4a07612efd66a559fe06810deee5e38cd96d03c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 27 Jun 2006 22:22:43 +0500 Subject: [PATCH 2/3] BUG#1662 - ALTER TABLE LIKE ignores DATA/INDEX DIRECTPORY Produce a warning if DATA/INDEX DIRECTORY is specified in ALTER TABLE statement. Ignoring of these options is documented in the symbolic links section of the manual. mysql-test/r/symlink.result: Modified test result according to fix for BUG#1662. sql/sql_parse.cc: Produce a warning if DATA/INDEX DIRECTORY is specified in ALTER TABLE statement. --- mysql-test/r/symlink.result | 6 ++++++ sql/sql_parse.cc | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result index caff53f8fd7..f6779689133 100644 --- a/mysql-test/r/symlink.result +++ b/mysql-test/r/symlink.result @@ -65,18 +65,24 @@ t9 CREATE TABLE `t9` ( ) ENGINE=MyISAM AUTO_INCREMENT=16725 DEFAULT CHARSET=latin1 DATA DIRECTORY='TEST_DIR/var/tmp/' INDEX DIRECTORY='TEST_DIR/var/run/' drop database mysqltest; create table t1 (a int not null) engine=myisam; +Warnings: +Warning 0 DATA DIRECTORY option ignored show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL default '0' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 alter table t1 add b int; +Warnings: +Warning 0 DATA DIRECTORY option ignored show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL default '0', `b` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 +Warnings: +Warning 0 INDEX DIRECTORY option ignored show create table t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 504339684ce..fbe36bfdc4a 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2678,6 +2678,12 @@ unsent_create_error: } } /* Don't yet allow changing of symlinks with ALTER TABLE */ + if (lex->create_info.data_file_name) + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, + "DATA DIRECTORY option ignored"); + if (lex->create_info.index_file_name) + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, + "INDEX DIRECTORY option ignored"); lex->create_info.data_file_name=lex->create_info.index_file_name=0; /* ALTER TABLE ends previous transaction */ if (end_active_trans(thd)) From 0b235009e60929ef254e20b48ae1254196580372 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 Jun 2006 14:27:37 +0200 Subject: [PATCH 3/3] Bug#17877 - Corrupted spatial index CHECK TABLE could complain about a fully intact spatial index. A wrong comparison operator was used for table checking. The result was that it checked for non-matching spatial keys. This succeeded if at least two different keys were present, but failed if only the matching key was present. I fixed the key comparison. myisam/mi_check.c: Bug#17877 - Corrupted spatial index Fixed the comparison operator for checking a spatial index. Using MBR_EQUAL | MBR_DATA to compare for equality and include the data pointer in the comparison. The latter finds the index entry that points to the current record. This is necessary for non-unique indexes. The old operator, SEARCH_SAME, is unknown to the rtree search functions and handled like MBR_DISJOINT. myisam/mi_key.c: Bug#17877 - Corrupted spatial index Added a missing DBUG_RETURN. myisam/rt_index.c: Bug#17877 - Corrupted spatial index Included the data pointer in the copy of the search key. This is necessary for searching the index entry that points to a specific record if the search_flag contains MBR_DATA. myisam/rt_mbr.c: Bug#17877 - Corrupted spatial index Extended the RT_CMP() macro with an assert for an unexpected comparison operator. mysql-test/r/gis-rtree.result: Bug#17877 - Corrupted spatial index The test result. mysql-test/t/gis-rtree.test: Bug#17877 - Corrupted spatial index The test case. --- myisam/mi_check.c | 5 ++-- myisam/mi_key.c | 2 +- myisam/rt_index.c | 8 ++++--- myisam/rt_mbr.c | 6 ++++- mysql-test/r/gis-rtree.result | 40 +++++++++++++++++++++++++++++++ mysql-test/t/gis-rtree.test | 44 +++++++++++++++++++++++++++++++++++ 6 files changed, 98 insertions(+), 7 deletions(-) diff --git a/myisam/mi_check.c b/myisam/mi_check.c index 2395640d5bf..1e62e5e641d 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -1155,12 +1155,13 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) */ int search_result= (keyinfo->flag & HA_SPATIAL) ? rtree_find_first(info, key, info->lastkey, key_length, - SEARCH_SAME) : + MBR_EQUAL | MBR_DATA) : _mi_search(info,keyinfo,info->lastkey,key_length, SEARCH_SAME, info->s->state.key_root[key]); if (search_result) { - mi_check_print_error(param,"Record at: %10s Can't find key for index: %2d", + mi_check_print_error(param,"Record at: %10s " + "Can't find key for index: %2d", llstr(start_recpos,llbuff),key+1); if (error++ > MAXERR || !(param->testflag & T_VERBOSE)) goto err2; diff --git a/myisam/mi_key.c b/myisam/mi_key.c index cb85febd869..eaa854b1a37 100644 --- a/myisam/mi_key.c +++ b/myisam/mi_key.c @@ -54,7 +54,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, TODO: nulls processing */ #ifdef HAVE_SPATIAL - return sp_make_key(info,keynr,key,record,filepos); + DBUG_RETURN(sp_make_key(info,keynr,key,record,filepos)); #else DBUG_ASSERT(0); /* mi_open should check that this never happens*/ #endif diff --git a/myisam/rt_index.c b/myisam/rt_index.c index 97554dca4e6..1806476dc39 100644 --- a/myisam/rt_index.c +++ b/myisam/rt_index.c @@ -183,9 +183,11 @@ int rtree_find_first(MI_INFO *info, uint keynr, uchar *key, uint key_length, return -1; } - /* Save searched key */ - memcpy(info->first_mbr_key, key, keyinfo->keylength - - info->s->base.rec_reflength); + /* + Save searched key, include data pointer. + The data pointer is required if the search_flag contains MBR_DATA. + */ + memcpy(info->first_mbr_key, key, keyinfo->keylength); info->last_rkey_length = key_length; info->rtree_recursion_depth = -1; diff --git a/myisam/rt_mbr.c b/myisam/rt_mbr.c index c43daec2f7c..897862c1c9a 100644 --- a/myisam/rt_mbr.c +++ b/myisam/rt_mbr.c @@ -52,10 +52,14 @@ if (EQUAL_CMP(amin, amax, bmin, bmax)) \ return 1; \ } \ - else /* if (nextflag & MBR_DISJOINT) */ \ + else if (nextflag & MBR_DISJOINT) \ { \ if (DISJOINT_CMP(amin, amax, bmin, bmax)) \ return 1; \ + }\ + else /* if unknown comparison operator */ \ + { \ + DBUG_ASSERT(0); \ } #define RT_CMP_KORR(type, korr_func, len, nextflag) \ diff --git a/mysql-test/r/gis-rtree.result b/mysql-test/r/gis-rtree.result index f479fc41ffb..3fcae8843c0 100644 --- a/mysql-test/r/gis-rtree.result +++ b/mysql-test/r/gis-rtree.result @@ -817,3 +817,43 @@ check table t1 extended; Table Op Msg_type Msg_text test.t1 check status OK drop table t1; +CREATE TABLE t1 ( +c1 geometry NOT NULL default '', +SPATIAL KEY i1 (c1(32)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +INSERT INTO t1 (c1) VALUES ( +PolygonFromText('POLYGON((-18.6086111000 -66.9327777000, + -18.6055555000 -66.8158332999, + -18.7186111000 -66.8102777000, + -18.7211111000 -66.9269443999, + -18.6086111000 -66.9327777000))')); +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; +CREATE TABLE t1 ( +c1 geometry NOT NULL default '', +SPATIAL KEY i1 (c1(32)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +INSERT INTO t1 (c1) VALUES ( +PolygonFromText('POLYGON((-18.6086111000 -66.9327777000, + -18.6055555000 -66.8158332999, + -18.7186111000 -66.8102777000, + -18.7211111000 -66.9269443999, + -18.6086111000 -66.9327777000))')); +INSERT INTO t1 (c1) VALUES ( +PolygonFromText('POLYGON((-65.7402776999 -96.6686111000, + -65.7372222000 -96.5516666000, + -65.8502777000 -96.5461111000, + -65.8527777000 -96.6627777000, + -65.7402776999 -96.6686111000))')); +INSERT INTO t1 (c1) VALUES ( +PolygonFromText('POLYGON((-18.6086111000 -66.9327777000, + -18.6055555000 -66.8158332999, + -18.7186111000 -66.8102777000, + -18.7211111000 -66.9269443999, + -18.6086111000 -66.9327777000))')); +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; diff --git a/mysql-test/t/gis-rtree.test b/mysql-test/t/gis-rtree.test index 682f67c61c4..eba53a8a9c5 100644 --- a/mysql-test/t/gis-rtree.test +++ b/mysql-test/t/gis-rtree.test @@ -188,4 +188,48 @@ check table t1 extended; drop table t1; +# +# Bug#17877 - Corrupted spatial index +# +CREATE TABLE t1 ( + c1 geometry NOT NULL default '', + SPATIAL KEY i1 (c1(32)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +INSERT INTO t1 (c1) VALUES ( + PolygonFromText('POLYGON((-18.6086111000 -66.9327777000, + -18.6055555000 -66.8158332999, + -18.7186111000 -66.8102777000, + -18.7211111000 -66.9269443999, + -18.6086111000 -66.9327777000))')); +# This showed a missing key. +CHECK TABLE t1 EXTENDED; +DROP TABLE t1; +# +CREATE TABLE t1 ( + c1 geometry NOT NULL default '', + SPATIAL KEY i1 (c1(32)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +INSERT INTO t1 (c1) VALUES ( + PolygonFromText('POLYGON((-18.6086111000 -66.9327777000, + -18.6055555000 -66.8158332999, + -18.7186111000 -66.8102777000, + -18.7211111000 -66.9269443999, + -18.6086111000 -66.9327777000))')); +INSERT INTO t1 (c1) VALUES ( + PolygonFromText('POLYGON((-65.7402776999 -96.6686111000, + -65.7372222000 -96.5516666000, + -65.8502777000 -96.5461111000, + -65.8527777000 -96.6627777000, + -65.7402776999 -96.6686111000))')); +# This is the same as the first insert to get a non-unique key. +INSERT INTO t1 (c1) VALUES ( + PolygonFromText('POLYGON((-18.6086111000 -66.9327777000, + -18.6055555000 -66.8158332999, + -18.7186111000 -66.8102777000, + -18.7211111000 -66.9269443999, + -18.6086111000 -66.9327777000))')); +# This showed (and still shows) OK. +CHECK TABLE t1 EXTENDED; +DROP TABLE t1; + # End of 4.1 tests