diff options
-rw-r--r-- | Docs/MySQLEULA.txt | 252 | ||||
-rw-r--r-- | README | 14 | ||||
-rw-r--r-- | configure.in | 7 | ||||
-rw-r--r-- | include/my_time.h | 32 | ||||
-rw-r--r-- | mysql-test/r/func_time.result | 40 | ||||
-rw-r--r-- | mysql-test/r/rename.result | 2 | ||||
-rw-r--r-- | mysql-test/r/timezone.result | 8 | ||||
-rw-r--r-- | mysql-test/r/timezone2.result | 24 | ||||
-rw-r--r-- | mysql-test/r/timezone4.result | 6 | ||||
-rw-r--r-- | mysql-test/t/func_time.test | 52 | ||||
-rw-r--r-- | mysql-test/t/rename.test | 8 | ||||
-rw-r--r-- | mysql-test/t/timezone.test | 7 | ||||
-rw-r--r-- | mysql-test/t/timezone2.test | 10 | ||||
-rw-r--r-- | mysql-test/t/timezone4-master.opt | 1 | ||||
-rw-r--r-- | mysql-test/t/timezone4.test | 13 | ||||
-rw-r--r-- | scripts/make_binary_distribution.sh | 7 | ||||
-rw-r--r-- | sql-common/my_time.c | 125 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 9 | ||||
-rw-r--r-- | sql/mysql_priv.h | 6 | ||||
-rw-r--r-- | sql/time.cc | 9 | ||||
-rw-r--r-- | sql/tztime.cc | 77 |
21 files changed, 376 insertions, 333 deletions
diff --git a/Docs/MySQLEULA.txt b/Docs/MySQLEULA.txt deleted file mode 100644 index f50c50298b1..00000000000 --- a/Docs/MySQLEULA.txt +++ /dev/null @@ -1,252 +0,0 @@ - License Agreement for Commercial Use of MySQL[tm] Software - -This Agreement ("License") is between MySQL AB, a Swedish company -("Licensor"), and the customer ("Licensee") identified on the electronic order -form submitted on behalf of Licensee (the "Order Form"). In consideration of -the mutual promises, covenants and conditions contained herein, the -sufficiency of which is hereby acknowledged, the parties agree as follows. - -1. License Grant. -"Licensed Software" means a complete and unchanged copy of the object code -version of the MySQL relational database management software identified in the -Order Form and posted on a special download page of the MySQL AB web site (the -"Download Page") made available to Licensee immediately after payment as -provided in Section 4. Subject to payment and the other terms and conditions -hereof, Licensor grants to Licensee a limited, non-exclusive and -non-transferable right to: (a) make one copy of the Licensed Software for each -license purchased (each, a "Licensed Copy"); (b) compile and/or link each -Licensed Copy to one copy of the Licensee software identified in the Order -Form (the "Licensee Application") without modifying the Licensed Software -(each, an "Integrated Product"); and (c) load and use the Licensed Copy -portion of an Integrated Product on one machine or instrument in the operating -system environment(s), and on the hardware platform(s) specified in the Order -Form, and solely for running and extracting data from, the Licensee -Application. "Use" means operation by one person for internal business -purposes in accordance with the terms and conditions hereof. Licensed Copies -shall be deemed accepted by Licensee immediately upon download. Licensee may -make one additional copy of each Licensed Copy for backup and archival -purposes only. - -2. Transfer. -Only after Licensee has linked or compiled a Licensed Copy as permitted in -Section 1, Licensee may transfer to a third party (the "Transferee") the right -to use such copy as described in Section 1. As a condition to any such -transfer: (a) Licensee must deliver the Licensed Copy and any backup copy to -the Transferee along with a copy of this License (including the Sales Order); -and (b) the Transferee must accept the terms and conditions of this License. -Any and all of Licensee's rights to a Licensed Copy shall terminate upon -transfer of the right to use such copy. A Transferee's rights are limited to -the use rights described in Section 1(c), and do not include the linking, -compilation or copying rights (except for backup and archival copies) -described in Section 1. If you did not purchase this License directly from -MySQL AB, then you are a Transferee. Licensee and any Transferee must comply -with all applicable export laws and regulations. - -3. Restrictions. -Licensee may use the Licensed Software only as expressly provided in Section -1. Without limiting the foregoing, Licensee shall not: (a) lease, license, -use, make available, distribute or modify all or any part of the Licensed -Software to any third party, except as otherwise expressly permitted herein; -(b) use the Licensed Software to operate in or as a time-sharing, outsourcing, -service bureau, application service provider or managed service provider -environment; (c) lease, license, use, make available or distribute the -Licensed Software as a general SQL server, as a stand alone application or -with applications other than the Licensee Application under this License; (d) -copy the Licensed Software onto any public or distributed network; (e) -distribute Integrated Products pursuant to a public or open source license; -(f) port the Licensed Software to any operating system other than as described -in the Order Form; or (g) change any proprietary rights notices which appear -in the Licensed Software. Except as otherwise provided in Section 2, the -rights granted to Licensee herein are rights that may be exercised solely by -Licensee. - -4. Price and payment. -No later than thirty (30) days after submission of the Order Form, Licensee -shall remit one non-refundable license fee per Licensed Copy as posted on -http://shop.mysql.com on the date Licensee submitted the Order Form (the -"License Fee"). All payments shall be made in Euros or U.S. dollars. Licensee -shall be responsible for paying all local, state, federal and international -sales, value added, excise and other taxes and duties payable in connection -with this License, other than taxes based upon Licensor's net income. Licensee -shall not be permitted to access the Download Page until Licensor has received -payment in full. - -5. Termination. -Licensor may terminate this License immediately if the Licensee shall breach -any of the provisions of this License and such breach remains uncured 30 days -after receipt of notice. In the event that Licensee becomes liquidated, -dissolved, bankrupt or insolvent, whether voluntarily or involuntarily, or -shall take any action to be so declared, Licensor shall have the right to -terminate this License immediately. Upon expiration, cancellation or other -termination of this License, Licensee shall immediately: (a) discontinue -distribution of Integrated Products that include Licensed Software; and (b) -destroy all copies of the Licensed Software, including (without limitation) as -linked or compiled in any Integrated Product. Sections 4 through 10 shall -survive the termination of this License for any reason. - -6. Proprietary Rights. -Licensee agrees that the copyright, patent, trade secrets and all other -intellectual proprietary rights of whatever nature in the Licensed Software -and related documentation, including derivative works, are and shall remain -the exclusive property of Licensor and any third party suppliers. Nothing in -this License should be construed as transferring any aspects of such rights to -Licensee or any third party. Licensor reserves any and all rights not -expressly granted herein. MySQL is a trademark of MySQL AB, and shall not be -used by Licensee without Licensor's express written authorization. Licensee -shall include in the Integrated Products a conspicuous notice that the -Integrated Products include software whose copyright is owned by MySQL AB. - -7. Disclaimer of Warranties. -THE LICENSED SOFTWARE IS LICENSED "AS IS," WITHOUT ANY WARRANTIES WHATSOEVER. -LICENSOR EXPRESSLY DISCLAIMS, AND LICENSEE EXPRESSLY WAIVES, ALL WARRANTIES, -WHETHER EXPRESS OR IMPLIED, INCLUDING WARRANTIES OF MERCHANTIBILITY, FITNESS -FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, SYSTEM INTEGRATION, -NON-INTERFERENCE AND ACCURACY OF INFORMATIONAL CONTENT. LICENSOR DOES NOT -WARRANT THAT THE LICENSED SOFTWARE WILL MEET LICENSEE'S REQUIREMENTS OR THAT -THE OPERATION OF THE LICENSED SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE, OR -THAT ERRORS WILL BE CORRECTED. THE ENTIRE RISK OF THE LICENSED SOFTWARE'S -QUALITY AND PERFORMANCE IS WITH LICENSEE. Without limiting the generality of -the foregoing disclaimer, Licensee acknowledges that the Licensed Software is -not specifically designed, manufactured or intended for use in the planning, -construction, maintenance, control or direct operation of nuclear facilities, -aircraft navigation, control or communication systems, weapons systems or -direct life support systems. - -8. Indemnification. -Licensee hereby indemnifies and agrees to defend Licensor against any and all -damages, judgments and costs (including reasonable attorneys' fees) related to -any claim based upon: (a) an allegation that the Licensee Application -infringes the intellectual property of a third party; (b) use of the Licensed -Software in a manner prohibited under this License or in a manner for which -the Licensed Software was not designed; (c) integration or use of the Licensed -Software with the Licensee Application (where use of the Licensed Software -alone would not infringe); (d) changes made by Licensee to the Licensed -Software (where use of unmodified Licensed Software would not infringe); (e) -changes made, or actions taken, by Licensor upon Licensee's direct -instructions; or (f) bodily injury, property damage or any other damage or -injury due to the use or inability to use an Integrated Product. - -9. Limitation of Liability. -LICENSOR SHALL HAVE NO LIABILITY WITH RESPECT TO ITS OBLIGATIONS UNDER THIS -AGREEMENT OR OTHERWISE FOR CONSEQUENTIAL, EXEMPLARY, SPECIAL, INDIRECT, -INCIDENTAL OR PUNITIVE DAMAGES, INCLUDING (WITHOUT LIMITATION) ANY LOST -PROFITS OR LOST SAVINGS (WHETHER RESULTING FROM IMPAIRED OR LOST DATA, -SOFTWARE OR COMPUTER FAILURE OR ANY OTHER CAUSE), EVEN IF IT HAS BEEN ADVISED -OF THE POSSIBILITY OF SUCH DAMAGES. NOTWITHSTANDING ANY OTHER PROVISION IN -THIS AGREEMENT, THE LIABILITY OF LICENSOR FOR ANY REASON AND UPON ANY CAUSE OF -ACTION SHALL BE LIMITED TO THE AMOUNT PAID TO LICENSOR BY LICENSEE UNDER THIS -AGREEMENT. THIS LIMITATION APPLIES TO ALL CAUSES OF ACTION IN THE AGGREGATE, -INCLUDING (WITHOUT LIMITATION) BREACH OF CONTRACT, BREACH OF WARRANTY, -NEGLIGENCE, MISREPRESENTATIONS AND OTHER TORTS. THE PARTIES AGREE THAT THE -REMEDIES AND LIMITATIONS HEREIN ALLOCATE THE RISKS BETWEEN THE PARTIES AS -AUTHORIZED BY APPLICABLE LAWS. THE LICENSE FEES ARE SET IN RELIANCE UPON THIS -ALLOCATION OF RISK AND THE EXCLUSION OF CERTAIN DAMAGES AS SET FORTH IN THIS -AGREEMENT. - -10. Miscellaneous. - -10.1 Interpretation. -Failure by Licensor to exercise any right or remedy does not signify -acceptance of the event giving rise to such right or remedy. No action arising -out of this License may be brought by Licensee more than one year after the -cause of action has accrued. If any part of this License is held by a court of -competent jurisdiction to be illegal or unenforceable, the validity or -enforceability of the remainder of this License shall not be affected and such -provision shall be deemed modified to the minimum extent necessary to make -such provision consistent with applicable law and, in its modified form, such -provision shall be enforceable and enforced. Licensor reserves the right not -to accept any Order Form. Any invoice issued by Licensor in connection with -this License shall be deemed a part of this Agreement. To the extent of any -inconsistency between an Order Form and an invoice issued by Licensor, the -terms and conditions of the invoice shall prevail; Licensee shall be deemed to -have accepted an invoice upon payment of such invoice. In the event that -Licensee placed an order by telephone or through an authorized sales -representative, the invoice issued by Licensor shall constitute the Order -Form. The terms and conditions of this Agreement shall replace and serve as a -novation of the terms and conditions of any commercial (i.e., non-GPL) license -purchased online by Licensee prior to August 2002. - -10.2 Binding. -This Agreement will be binding upon and inure to the benefit of the parties, -their respective successors and permitted assigns. Except as otherwise -provided in Section 2, without the prior written consent of Licensor, Licensee -may not assign this License or its rights or obligations under this License to -any person or party, whether by operation of law or otherwise; any attempt by -Licensee to assign this License without Licensor's prior written consent shall -be null and void. There are no intended third party beneficiaries of this -License. The parties are, and shall remain, independent contractors; nothing -in this License is designed to create, nor shall create between them, a -partnership, joint venture, agency, or employment relationship. - -10.3 Governing Law; Dispute Forum. -If Licensee's residence, principal place of business or place of organization -is in the United States of America ("USA"), then this License shall be deemed -to have been executed in the USA and shall be governed by the laws of the -State of Delaware, without regard to the conflict of laws provisions thereof. -If Licensee's residence, principal place of business or place of organization -is in any country other than the USA, then this License shall be deemed to -have been executed in Sweden and shall be governed by the laws of Sweden, -without regard to the conflict of laws provisions thereof. In no event shall -the United Nations Convention on Contracts for the International Sale of Goods -apply to, or govern, this License. The parties consent to the exclusive -jurisdiction of the courts of Sweden and the USA, as provided in this Section. -In the event that Licensor initiates an action in connection with this License -or any other dispute between the parties, the exclusive jurisdiction of such -action shall be in: (a) Newark, Delaware, if Licensee's residence, principal -place of business or place of organization is in the USA; or (b) Uppsala, -Sweden, if Licensee's residence, principal place of business or place of -organization is in any country other than the USA. In the event that Licensee -initiates an action in connection with this License or any other dispute -between the parties, the exclusive jurisdiction of such action shall be in -Stockholm, Sweden. Notwithstanding the foregoing, either party may bring a -counterclaim in an action in the same jurisdiction in which the originating -claim was filed, and either party may enforce any judgment rendered by such -court in any court of competent jurisdiction. Licensee shall comply at its own -expense with all relevant and applicable laws related to use and distribution -of the Licensed Software as permitted in this License. Notwithstanding the -foregoing, Licensor may seek injunctive or other equitable relief in any -jurisdiction in order to protect its intellectual property rights. The parties -have agreed to execute this License in the English language, and the English -language version of the Agreement will control for all purposes. Any action -brought under this License shall be conducted in the English language. -Licensee shall be responsible for Licensor's attorneys fees and other expenses -associated with the enforcement of this License or the collection of any -amounts due under this License. - -10.4 Notice. -Unless otherwise agreed, any notice under this License shall be delivered and -addressed to Licensee at the address set forth on the Order Form, and to -Licensor at Bangardsgatan 8, 753 20, Uppsala, Sweden. Notice shall be deemed -received by any party: (a) on the day given, if personally delivered or if -sent by confirmed facsimile transmission, receipt verified; (b) on the third -day after deposit, if mailed by certified, first class, postage prepaid, -return receipt requested mail, or by reputable, expedited overnight courier; -or (c) on the fifth day after deposit, if sent by reputable, expedited -international courier. Either party may change its address for notice -purposes upon notice in accordance with this Section. Licensor may identify -Licensee as a commercial licensee, including on the MySQL web site. - -10.5 GPL. -The GPL License shall continue to apply to any and all uses and distributions -of the Licensed Software undertaken by Licensee either prior to the Effective -Date, after termination, or otherwise outside the scope of this License. This -Agreement shall not be deemed to replace or otherwise amend any Licensee -rights or obligations pursuant to the GPL License with respect to any uses of -the Licensed Software described in the preceding sentence. - -10.6 Entire Agreement. -This Agreement (including the Order Form and the invoice) comprises the entire -agreement, and supercedes and merges all prior proposals, understandings and -agreements, oral and written, between the parties relating to the subject -matter of this License. This Agreement may be amended or modified only in a -writing executed by both parties. To the extent of any conflict or -inconsistency between this License and any invoice or other document submitted -by Licensee to Licensor, this License will control. Licensor's acceptance of -any document shall not be construed as an acceptance of provisions which are -in any way in conflict or inconsistent with, or in addition to, this License, -unless such terms are separately and specifically accepted in writing by an -authorized officer of Licensor. - -10.7 Print this License. -For record keeping purposes, we encourage Licensee to print this License and -the Order Form on the date that the Order Form is submitted. @@ -2,8 +2,9 @@ This is a release of MySQL, a dual-license SQL database server. MySQL is brought to you by the MySQL team at MySQL AB. License information can be found in these files: -- For GPL (free) distributions, see the COPYING file. -- For commercial distributions, see the MySQLEULA.txt file. +- For GPL (free) distributions, see the COPYING file and + the EXCEPTIONS-CLIENT file. +- For commercial distributions, see the LICENSE.mysql file. For further information about MySQL or additional documentation, see: @@ -15,11 +16,10 @@ Some manual sections of special interest: - If you are migrating from an older version of MySQL, please read the "Upgrading from..." section first! - To see what MySQL can do, take a look at the features section. -- For installation instructions, see the Installation chapter. -- For future plans, see the TODO appendix. -- For the new features/bugfix history, see the News appendix. -- For the currently known bugs/misfeatures (known errors) see the problems - appendix. +- For installation instructions, see the Installing and Upgrading chapter. +- For the new features/bugfix history, see the Change History appendix. +- For the currently known bugs/misfeatures (known errors) see the Problems + and Common Errors appendix. - For a list of developers and other contributors, see the Credits appendix. diff --git a/configure.in b/configure.in index 5799a639314..d0c2cd87381 100644 --- a/configure.in +++ b/configure.in @@ -1781,6 +1781,13 @@ then AC_MSG_ERROR("MySQL needs a off_t type.") fi +dnl +dnl check if time_t is unsigned +dnl + +MYSQL_CHECK_TIME_T + + # do we need #pragma interface/#pragma implementation ? # yes if it's gcc 2.x, and not icc pretending to be gcc, and not cygwin AC_MSG_CHECKING(the need for @%:@pragma interface/implementation) diff --git a/include/my_time.h b/include/my_time.h index adce58b08d7..574f1a49c5a 100644 --- a/include/my_time.h +++ b/include/my_time.h @@ -38,6 +38,14 @@ typedef long my_time_t; #define MY_TIME_T_MAX LONG_MAX #define MY_TIME_T_MIN LONG_MIN + +/* Time handling defaults */ +#define TIMESTAMP_MAX_YEAR 2038 +#define YY_PART_YEAR 70 +#define TIMESTAMP_MIN_YEAR (1900 + YY_PART_YEAR - 1) +#define TIMESTAMP_MAX_VALUE INT_MAX32 +#define TIMESTAMP_MIN_VALUE 1 + #define YY_PART_YEAR 70 /* Flags to str_to_datetime */ @@ -80,6 +88,30 @@ uint calc_days_in_year(uint year); void init_time(void); + +/* + Function to check sanity of a TIMESTAMP value + + DESCRIPTION + Check if a given MYSQL_TIME value fits in TIMESTAMP range. + This function doesn't make precise check, but rather a rough + estimate. + + RETURN VALUES + FALSE The value seems sane + TRUE The MYSQL_TIME value is definitely out of range +*/ + +static inline bool validate_timestamp_range(const MYSQL_TIME *t) +{ + if ((t->year > TIMESTAMP_MAX_YEAR || t->year < TIMESTAMP_MIN_YEAR) || + (t->year == TIMESTAMP_MAX_YEAR && (t->month > 1 || t->day > 19)) || + (t->year == TIMESTAMP_MIN_YEAR && (t->month < 12 || t->day < 31))) + return FALSE; + + return TRUE; +} + my_time_t my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, my_bool *in_dst_time_gap); diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 7388ca3c2b8..e8fd7a4e4c9 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -550,12 +550,48 @@ unix_timestamp('1969-12-01 19:00:01') select from_unixtime(-1); from_unixtime(-1) NULL -select from_unixtime(2145916800); -from_unixtime(2145916800) +select from_unixtime(2147483647); +from_unixtime(2147483647) +2038-01-19 06:14:07 +select from_unixtime(2147483648); +from_unixtime(2147483648) NULL select from_unixtime(0); from_unixtime(0) 1970-01-01 03:00:00 +select unix_timestamp(from_unixtime(2147483647)); +unix_timestamp(from_unixtime(2147483647)) +2147483647 +select unix_timestamp(from_unixtime(2147483648)); +unix_timestamp(from_unixtime(2147483648)) +NULL +select unix_timestamp('2039-01-20 01:00:00'); +unix_timestamp('2039-01-20 01:00:00') +0 +select unix_timestamp('1968-01-20 01:00:00'); +unix_timestamp('1968-01-20 01:00:00') +0 +select unix_timestamp('2038-02-10 01:00:00'); +unix_timestamp('2038-02-10 01:00:00') +0 +select unix_timestamp('1969-11-20 01:00:00'); +unix_timestamp('1969-11-20 01:00:00') +0 +select unix_timestamp('2038-01-20 01:00:00'); +unix_timestamp('2038-01-20 01:00:00') +0 +select unix_timestamp('1969-12-30 01:00:00'); +unix_timestamp('1969-12-30 01:00:00') +0 +select unix_timestamp('2038-01-17 12:00:00'); +unix_timestamp('2038-01-17 12:00:00') +2147331600 +select unix_timestamp('1970-01-01 03:00:01'); +unix_timestamp('1970-01-01 03:00:01') +1 +select unix_timestamp('2038-01-19 07:14:07'); +unix_timestamp('2038-01-19 07:14:07') +0 CREATE TABLE t1 (datetime datetime, timestamp timestamp, date date, time time); INSERT INTO t1 values ("2001-01-02 03:04:05", "2002-01-02 03:04:05", "2003-01-02", "06:07:08"); SELECT * from t1; diff --git a/mysql-test/r/rename.result b/mysql-test/r/rename.result index 51c2ce3a1b9..1257a668cce 100644 --- a/mysql-test/r/rename.result +++ b/mysql-test/r/rename.result @@ -54,6 +54,7 @@ Tables_in_test t2 t4 drop table t2, t4; +End of 4.1 tests create table t1(f1 int); create view v1 as select * from t1; alter table v1 rename to v2; @@ -64,3 +65,4 @@ rename table v2 to v1; ERROR 42S01: Table 'v1' already exists drop view v1; drop table t1; +End of 5.0 tests diff --git a/mysql-test/r/timezone.result b/mysql-test/r/timezone.result index 10944c3706e..1223fff36c6 100644 --- a/mysql-test/r/timezone.result +++ b/mysql-test/r/timezone.result @@ -41,7 +41,7 @@ Warning 1299 Invalid TIMESTAMP value in column 'ts' at row 2 DROP TABLE t1; select unix_timestamp('1970-01-01 01:00:00'), unix_timestamp('1970-01-01 01:00:01'), -unix_timestamp('2038-01-01 00:59:59'), -unix_timestamp('2038-01-01 01:00:00'); -unix_timestamp('1970-01-01 01:00:00') unix_timestamp('1970-01-01 01:00:01') unix_timestamp('2038-01-01 00:59:59') unix_timestamp('2038-01-01 01:00:00') -0 1 2145916799 0 +unix_timestamp('2038-01-19 04:14:07'), +unix_timestamp('2038-01-19 04:14:08'); +unix_timestamp('1970-01-01 01:00:00') unix_timestamp('1970-01-01 01:00:01') unix_timestamp('2038-01-19 04:14:07') unix_timestamp('2038-01-19 04:14:08') +0 1 2147483647 0 diff --git a/mysql-test/r/timezone2.result b/mysql-test/r/timezone2.result index a1ae2f63212..bb1d764ac8c 100644 --- a/mysql-test/r/timezone2.result +++ b/mysql-test/r/timezone2.result @@ -116,7 +116,7 @@ create table t1 (ts timestamp); set time_zone='UTC'; insert into t1 values ('0000-00-00 00:00:00'),('1969-12-31 23:59:59'), ('1970-01-01 00:00:00'),('1970-01-01 00:00:01'), -('2037-12-31 23:59:59'),('2038-01-01 00:00:00'); +('2038-01-19 03:14:07'),('2038-01-19 03:14:08'); Warnings: Warning 1264 Out of range value adjusted for column 'ts' at row 2 Warning 1264 Out of range value adjusted for column 'ts' at row 3 @@ -127,13 +127,13 @@ ts 0000-00-00 00:00:00 0000-00-00 00:00:00 1970-01-01 00:00:01 -2037-12-31 23:59:59 +2038-01-19 03:14:07 0000-00-00 00:00:00 delete from t1; set time_zone='MET'; insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 00:30:00'), ('1970-01-01 01:00:00'),('1970-01-01 01:00:01'), -('2038-01-01 00:59:59'),('2038-01-01 01:00:00'); +('2038-01-19 04:14:07'),('2038-01-19 04:14:08'); Warnings: Warning 1264 Out of range value adjusted for column 'ts' at row 2 Warning 1264 Out of range value adjusted for column 'ts' at row 3 @@ -144,13 +144,13 @@ ts 0000-00-00 00:00:00 0000-00-00 00:00:00 1970-01-01 01:00:01 -2038-01-01 00:59:59 +2038-01-19 04:14:07 0000-00-00 00:00:00 delete from t1; set time_zone='+01:30'; insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 01:00:00'), ('1970-01-01 01:30:00'),('1970-01-01 01:30:01'), -('2038-01-01 01:29:59'),('2038-01-01 01:30:00'); +('2038-01-19 04:44:07'),('2038-01-19 04:44:08'); Warnings: Warning 1264 Out of range value adjusted for column 'ts' at row 2 Warning 1264 Out of range value adjusted for column 'ts' at row 3 @@ -161,7 +161,7 @@ ts 0000-00-00 00:00:00 0000-00-00 00:00:00 1970-01-01 01:30:01 -2038-01-01 01:29:59 +2038-01-19 04:44:07 0000-00-00 00:00:00 drop table t1; show variables like 'time_zone'; @@ -223,12 +223,12 @@ convert_tz('2003-10-26 02:59:59', 'MET', 'UTC') select convert_tz('2003-10-26 04:00:00', 'MET', 'UTC'); convert_tz('2003-10-26 04:00:00', 'MET', 'UTC') 2003-10-26 03:00:00 -select convert_tz('2038-01-01 00:59:59', 'MET', 'UTC'); -convert_tz('2038-01-01 00:59:59', 'MET', 'UTC') -2037-12-31 23:59:59 -select convert_tz('2038-01-01 01:00:00', 'MET', 'UTC'); -convert_tz('2038-01-01 01:00:00', 'MET', 'UTC') -2038-01-01 01:00:00 +select convert_tz('2038-01-19 04:14:07', 'MET', 'UTC'); +convert_tz('2038-01-19 04:14:07', 'MET', 'UTC') +2038-01-19 03:14:07 +select convert_tz('2038-01-19 04:14:08', 'MET', 'UTC'); +convert_tz('2038-01-19 04:14:08', 'MET', 'UTC') +2038-01-19 04:14:08 select convert_tz('2103-01-01 04:00:00', 'MET', 'UTC'); convert_tz('2103-01-01 04:00:00', 'MET', 'UTC') 2103-01-01 04:00:00 diff --git a/mysql-test/r/timezone4.result b/mysql-test/r/timezone4.result new file mode 100644 index 00000000000..28028bea657 --- /dev/null +++ b/mysql-test/r/timezone4.result @@ -0,0 +1,6 @@ +select from_unixtime(0); +from_unixtime(0) +1969-12-31 14:00:00 +select unix_timestamp('1969-12-31 14:00:01'); +unix_timestamp('1969-12-31 14:00:01') +1 diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index ae3811a3257..a3985998b13 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -255,17 +255,57 @@ select unix_timestamp(@a); select unix_timestamp('1969-12-01 19:00:01'); # -# Test for bug #6439 "unix_timestamp() function returns wrong datetime -# values for too big argument" and bug #7515 "from_unixtime(0) now -# returns NULL instead of the epoch". unix_timestamp() should return error -# for too big or negative argument. It should return Epoch value for zero -# argument since it seems that many user's rely on this fact. +# Tests for bug #6439 "unix_timestamp() function returns wrong datetime +# values for too big argument", bug #7515 "from_unixtime(0) now +# returns NULL instead of the epoch" and bug #9191 +# "TIMESTAMP/from_unixtime() no longer accepts 2^31-1." +# unix_timestamp() should return error for too big or negative argument. +# It should return Epoch value for zero argument since it seems that many +# users rely on this fact, from_unixtime() should work with values +# up to INT_MAX32 because of the same reason. # select from_unixtime(-1); -select from_unixtime(2145916800); +# check for from_unixtime(2^31-1) and from_unixtime(2^31) +select from_unixtime(2147483647); +select from_unixtime(2147483648); select from_unixtime(0); # +# Some more tests for bug #9191 "TIMESTAMP/from_unixtime() no +# longer accepts 2^31-1". Here we test that from_unixtime and +# unix_timestamp are consistent, when working with boundary dates. +# +select unix_timestamp(from_unixtime(2147483647)); +select unix_timestamp(from_unixtime(2147483648)); + +# check for invalid dates + +# bad year +select unix_timestamp('2039-01-20 01:00:00'); +select unix_timestamp('1968-01-20 01:00:00'); +# bad month +select unix_timestamp('2038-02-10 01:00:00'); +select unix_timestamp('1969-11-20 01:00:00'); +# bad day +select unix_timestamp('2038-01-20 01:00:00'); +select unix_timestamp('1969-12-30 01:00:00'); + +# +# Check negative shift (we subtract several days for boundary dates during +# conversion). +select unix_timestamp('2038-01-17 12:00:00'); + +# +# Check positive shift. (it happens only on +# platfroms with unsigned time_t, such as QNX) +# +select unix_timestamp('1970-01-01 03:00:01'); + +# check bad date, close to the boundary (we cut them off in the very end) +select unix_timestamp('2038-01-19 07:14:07'); + + +# # Test types from + INTERVAL # diff --git a/mysql-test/t/rename.test b/mysql-test/t/rename.test index 5c750711853..09a02344203 100644 --- a/mysql-test/t/rename.test +++ b/mysql-test/t/rename.test @@ -77,6 +77,10 @@ disconnect con2; disconnect con1; connection default; + +--echo End of 4.1 tests + + # # Bug#14959: ALTER TABLE isn't able to rename a view # @@ -90,4 +94,6 @@ rename table v2 to v1; rename table v2 to v1; drop view v1; drop table t1; -# End of 4.1 tests + + +--echo End of 5.0 tests diff --git a/mysql-test/t/timezone.test b/mysql-test/t/timezone.test index 34bbb365c70..157b18f57fa 100644 --- a/mysql-test/t/timezone.test +++ b/mysql-test/t/timezone.test @@ -52,11 +52,12 @@ INSERT INTO t1 (ts) VALUES ('2003-03-30 01:59:59'), DROP TABLE t1; # -# Test for fix for Bug#2523 +# Test for fix for Bug#2523 Check that boundary dates are processed +# correctly. # select unix_timestamp('1970-01-01 01:00:00'), unix_timestamp('1970-01-01 01:00:01'), - unix_timestamp('2038-01-01 00:59:59'), - unix_timestamp('2038-01-01 01:00:00'); + unix_timestamp('2038-01-19 04:14:07'), + unix_timestamp('2038-01-19 04:14:08'); # End of 4.1 tests diff --git a/mysql-test/t/timezone2.test b/mysql-test/t/timezone2.test index bfc909d6995..75e5d4bfe81 100644 --- a/mysql-test/t/timezone2.test +++ b/mysql-test/t/timezone2.test @@ -113,21 +113,21 @@ create table t1 (ts timestamp); set time_zone='UTC'; insert into t1 values ('0000-00-00 00:00:00'),('1969-12-31 23:59:59'), ('1970-01-01 00:00:00'),('1970-01-01 00:00:01'), - ('2037-12-31 23:59:59'),('2038-01-01 00:00:00'); + ('2038-01-19 03:14:07'),('2038-01-19 03:14:08'); select * from t1; delete from t1; # MET time zone has range shifted by one hour set time_zone='MET'; insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 00:30:00'), ('1970-01-01 01:00:00'),('1970-01-01 01:00:01'), - ('2038-01-01 00:59:59'),('2038-01-01 01:00:00'); + ('2038-01-19 04:14:07'),('2038-01-19 04:14:08'); select * from t1; delete from t1; # same for +01:30 time zone set time_zone='+01:30'; insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 01:00:00'), ('1970-01-01 01:30:00'),('1970-01-01 01:30:01'), - ('2038-01-01 01:29:59'),('2038-01-01 01:30:00'); + ('2038-01-19 04:44:07'),('2038-01-19 04:44:08'); select * from t1; drop table t1; @@ -177,8 +177,8 @@ select convert_tz('2003-10-26 01:00:00', 'MET', 'UTC'); select convert_tz('2003-10-26 02:00:00', 'MET', 'UTC'); select convert_tz('2003-10-26 02:59:59', 'MET', 'UTC'); select convert_tz('2003-10-26 04:00:00', 'MET', 'UTC'); -select convert_tz('2038-01-01 00:59:59', 'MET', 'UTC'); -select convert_tz('2038-01-01 01:00:00', 'MET', 'UTC'); +select convert_tz('2038-01-19 04:14:07', 'MET', 'UTC'); +select convert_tz('2038-01-19 04:14:08', 'MET', 'UTC'); select convert_tz('2103-01-01 04:00:00', 'MET', 'UTC'); # Let us test variable time zone argument diff --git a/mysql-test/t/timezone4-master.opt b/mysql-test/t/timezone4-master.opt new file mode 100644 index 00000000000..d1ab6207933 --- /dev/null +++ b/mysql-test/t/timezone4-master.opt @@ -0,0 +1 @@ +--timezone=GMT+10 diff --git a/mysql-test/t/timezone4.test b/mysql-test/t/timezone4.test new file mode 100644 index 00000000000..d7372c75d5a --- /dev/null +++ b/mysql-test/t/timezone4.test @@ -0,0 +1,13 @@ +# +# Tests for time functions. The difference from func_time test is the +# timezone. In func_time it's GMT-3. In our case it's GMT+10 +# + +# +# Test for bug bug #9191 "TIMESTAMP/from_unixtime() no longer accepts 2^31-1" +# + +select from_unixtime(0); +# check 0 boundary +select unix_timestamp('1969-12-31 14:00:01'); + diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index d9e3ea27895..512e8a574ed 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -121,7 +121,7 @@ copyfileto() copyfileto $BASE/docs ChangeLog Docs/mysql.info copyfileto $BASE COPYING COPYING.LIB README Docs/INSTALL-BINARY \ - EXCEPTIONS-CLIENT MySQLEULA.txt LICENSE.doc README.NW + EXCEPTIONS-CLIENT LICENSE.mysql # Non platform-specific bin dir files: BIN_FILES="extra/comp_err$BS extra/replace$BS extra/perror$BS \ @@ -303,10 +303,7 @@ if [ $BASE_SYSTEM = "netware" ] ; then $BASE/support-files/build-tags \ $BASE/support-files/MySQL-shared-compat.spec \ $BASE/support-files/ndb-config-2-node.ini \ - $BASE/INSTALL-BINARY \ - $BASE/MySQLEULA.txt -else - rm -f $BASE/README.NW + $BASE/INSTALL-BINARY fi # Make safe_mysqld a symlink to mysqld_safe for backwards portability diff --git a/sql-common/my_time.c b/sql-common/my_time.c index fb36e5f4e54..2dd40c112de 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -778,16 +778,28 @@ long calc_daynr(uint year,uint month,uint day) RETURN VALUE Time in UTC seconds since Unix Epoch representation. */ -my_time_t -my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, - my_bool *in_dst_time_gap) +my_time_t +my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone, + bool *in_dst_time_gap) { uint loop; - time_t tmp; + time_t tmp= 0; + int shift= 0; + MYSQL_TIME tmp_time; + MYSQL_TIME *t= &tmp_time; struct tm *l_time,tm_tmp; long diff, current_timezone; /* + Use temp variable to avoid trashing input data, which could happen in + case of shift required for boundary dates processing. + */ + memcpy(&tmp_time, t_src, sizeof(MYSQL_TIME)); + + if (!validate_timestamp_range(t)) + return 0; + + /* Calculate the gmt time based on current time and timezone The -1 on the end is to ensure that if have a date that exists twice (like 2002-10-27 02:00:0 MET), we will find the initial date. @@ -800,13 +812,89 @@ my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, Note: this code assumes that our time_t estimation is not too far away from real value (we assume that localtime_r(tmp) will return something within 24 hrs from t) which is probably true for all current time zones. + + Note2: For the dates, which have time_t representation close to + MAX_INT32 (efficient time_t limit for supported platforms), we should + do a small trick to avoid overflow. That is, convert the date, which is + two days earlier, and then add these days to the final value. + + The same trick is done for the values close to 0 in time_t + representation for platfroms with unsigned time_t (QNX). + + To be more verbose, here is a sample (extracted from the code below): + (calc_daynr(2038, 1, 19) - (long) days_at_timestart)*86400L + 4*3600L + would return -2147480896 because of the long type overflow. In result + we would get 1901 year in localtime_r(), which is an obvious error. + + Alike problem raises with the dates close to Epoch. E.g. + (calc_daynr(1969, 12, 31) - (long) days_at_timestart)*86400L + 23*3600L + will give -3600. + + On some platforms, (E.g. on QNX) time_t is unsigned and localtime(-3600) + wil give us a date around 2106 year. Which is no good. + + Theoreticaly, there could be problems with the latter conversion: + there are at least two timezones, which had time switches near 1 Jan + of 1970 (because of political reasons). These are America/Hermosillo and + America/Mazatlan time zones. They changed their offset on + 1970-01-01 08:00:00 UTC from UTC-8 to UTC-7. For these zones + the code below will give incorrect results for dates close to + 1970-01-01, in the case OS takes into account these historical switches. + Luckily, it seems that we support only one platform with unsigned + time_t. It's QNX. And QNX does not support historical timezone data at all. + E.g. there are no /usr/share/zoneinfo/ files or any other mean to supply + historical information for localtime_r() etc. That is, the problem is not + relevant to QNX. + + We are safe with shifts close to MAX_INT32, as there are no known + time switches on Jan 2038 yet :) */ - tmp=(time_t) (((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) - - (long) days_at_timestart)*86400L + (long) t->hour*3600L + - (long) (t->minute*60 + t->second)) + (time_t) my_time_zone - - 3600); - current_timezone= my_time_zone; + if ((t->year == TIMESTAMP_MAX_YEAR) && (t->month == 1) && (t->day > 4)) + { + /* + Below we will pass (uint) (t->day - shift) to calc_daynr. + As we don't want to get an overflow here, we will shift + only safe dates. That's why we have (t->day > 4) above. + */ + t->day-= 2; + shift= 2; + } +#ifdef TIME_T_UNSIGNED + else + { + /* + We can get 0 in time_t representaion only on 1969, 31 of Dec or on + 1970, 1 of Jan. For both dates we use shift, which is added + to t->day in order to step out a bit from the border. + This is required for platforms, where time_t is unsigned. + As far as I know, among the platforms we support it's only QNX. + Note: the order of below if-statements is significant. + */ + if ((t->year == TIMESTAMP_MIN_YEAR + 1) && (t->month == 1) + && (t->day <= 10)) + { + t->day+= 2; + shift= -2; + } + + if ((t->year == TIMESTAMP_MIN_YEAR) && (t->month == 12) + && (t->day == 31)) + { + t->year++; + t->month= 1; + t->day= 2; + shift= -2; + } + } +#endif + + tmp= (time_t) (((calc_daynr((uint) t->year, (uint) t->month, (uint) t->day) - + (long) days_at_timestart)*86400L + (long) t->hour*3600L + + (long) (t->minute*60 + t->second)) + (time_t) my_time_zone - + 3600); + + current_timezone= my_time_zone; localtime_r(&tmp,&tm_tmp); l_time=&tm_tmp; for (loop=0; @@ -858,7 +946,24 @@ my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, *in_dst_time_gap= 1; } *my_timezone= current_timezone; - + + + /* shift back, if we were dealing with boundary dates */ + tmp+= shift*86400L; + + /* + This is possible for dates, which slightly exceed boundaries. + Conversion will pass ok for them, but we don't allow them. + First check will pass for platforms with signed time_t. + instruction above (tmp+= shift*86400L) could exceed + MAX_INT32 (== TIMESTAMP_MAX_VALUE) and overflow will happen. + So, tmp < TIMESTAMP_MIN_VALUE will be triggered. On platfroms + with unsigned time_t tmp+= shift*86400L might result in a number, + larger then TIMESTAMP_MAX_VALUE, so another check will work. + */ + if ((tmp < TIMESTAMP_MIN_VALUE) || (tmp > TIMESTAMP_MAX_VALUE)) + tmp= 0; +end: return (my_time_t) tmp; } /* my_system_gmt_sec */ diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index be924bd3585..a776d8a5ff7 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2035,17 +2035,14 @@ bool Item_func_convert_tz::get_date(TIME *ltime, return 1; } - /* Check if we in range where we treat datetime values as non-UTC */ - if (ltime->year < TIMESTAMP_MAX_YEAR && ltime->year > TIMESTAMP_MIN_YEAR || - ltime->year==TIMESTAMP_MAX_YEAR && ltime->month==1 && ltime->day==1 || - ltime->year==TIMESTAMP_MIN_YEAR && ltime->month==12 && ltime->day==31) { my_bool not_used; my_time_tmp= from_tz->TIME_to_gmt_sec(ltime, ¬_used); - if (my_time_tmp >= TIMESTAMP_MIN_VALUE && my_time_tmp <= TIMESTAMP_MAX_VALUE) + /* my_time_tmp is guranteed to be in the allowed range */ + if (my_time_tmp) to_tz->gmt_sec_to_TIME(ltime, my_time_tmp); } - + null_value= 0; return 0; } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 165bedb3659..cd6c2a73ccc 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -212,12 +212,6 @@ MY_LOCALE *my_locale_by_name(const char *name); /* Characters shown for the command in 'show processlist' */ #define PROCESS_LIST_WIDTH 100 -/* Time handling defaults */ -#define TIMESTAMP_MAX_YEAR 2038 -#define YY_PART_YEAR 70 -#define TIMESTAMP_MIN_YEAR (1900 + YY_PART_YEAR - 1) -#define TIMESTAMP_MAX_VALUE 2145916799 -#define TIMESTAMP_MIN_VALUE 1 #define PRECISION_FOR_DOUBLE 53 #define PRECISION_FOR_FLOAT 24 diff --git a/sql/time.cc b/sql/time.cc index c71ea08fb77..6c68d610207 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -229,14 +229,11 @@ my_time_t TIME_to_timestamp(THD *thd, const TIME *t, my_bool *in_dst_time_gap) *in_dst_time_gap= 0; - if (t->year < TIMESTAMP_MAX_YEAR && t->year > TIMESTAMP_MIN_YEAR || - t->year == TIMESTAMP_MAX_YEAR && t->month == 1 && t->day == 1 || - t->year == TIMESTAMP_MIN_YEAR && t->month == 12 && t->day == 31) + timestamp= thd->variables.time_zone->TIME_to_gmt_sec(t, in_dst_time_gap); + if (timestamp) { thd->time_zone_used= 1; - timestamp= thd->variables.time_zone->TIME_to_gmt_sec(t, in_dst_time_gap); - if (timestamp >= TIMESTAMP_MIN_VALUE && timestamp <= TIMESTAMP_MAX_VALUE) - return timestamp; + return timestamp; } /* If we are here we have range error. */ diff --git a/sql/tztime.cc b/sql/tztime.cc index d12aef47b40..bd8e43075c4 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -886,8 +886,14 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp, my_time_t local_t; uint saved_seconds; uint i; + int shift= 0; + DBUG_ENTER("TIME_to_gmt_sec"); + if (!validate_timestamp_range(t)) + DBUG_RETURN(0); + + /* We need this for correct leap seconds handling */ if (t->second < SECS_PER_MIN) saved_seconds= 0; @@ -895,11 +901,29 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp, saved_seconds= t->second; /* - NOTE If we want to convert full my_time_t range without MySQL - restrictions we should catch overflow here somehow. + NOTE: to convert full my_time_t range we do a shift of the + boundary dates here to avoid overflow of my_time_t. + We use alike approach in my_system_gmt_sec(). + + However in that function we also have to take into account + overflow near 0 on some platforms. That's because my_system_gmt_sec + uses localtime_r(), which doesn't work with negative values correctly + on platforms with unsigned time_t (QNX). Here we don't use localtime() + => we negative values of local_t are ok. */ - local_t= sec_since_epoch(t->year, t->month, t->day, + if ((t->year == TIMESTAMP_MAX_YEAR) && (t->month == 1) && t->day > 4) + { + /* + We will pass (t->day - shift) to sec_since_epoch(), and + want this value to be a positive number, so we shift + only dates > 4.01.2038 (to avoid owerflow). + */ + shift= 2; + } + + + local_t= sec_since_epoch(t->year, t->month, (t->day - shift), t->hour, t->minute, saved_seconds ? 0 : t->second); @@ -918,6 +942,22 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp, /* binary search for our range */ i= find_time_range(local_t, sp->revts, sp->revcnt); + /* + As there are no offset switches at the end of TIMESTAMP range, + we could simply check for overflow here (and don't need to bother + about DST gaps etc) + */ + if (shift) + { + if (local_t > (TIMESTAMP_MAX_VALUE - shift*86400L + + sp->revtis[i].rt_offset - saved_seconds)) + { + DBUG_RETURN(0); /* my_time_t overflow */ + } + else + local_t+= shift*86400L; + } + if (sp->revtis[i].rt_type) { /* @@ -927,10 +967,16 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp, beginning of the gap. */ *in_dst_time_gap= 1; - DBUG_RETURN(sp->revts[i] - sp->revtis[i].rt_offset + saved_seconds); + local_t= sp->revts[i] - sp->revtis[i].rt_offset + saved_seconds; } else - DBUG_RETURN(local_t - sp->revtis[i].rt_offset + saved_seconds); + local_t= local_t - sp->revtis[i].rt_offset + saved_seconds; + + /* check for TIMESTAMP_MAX_VALUE was already done above */ + if (local_t < TIMESTAMP_MIN_VALUE) + local_t= 0; + + DBUG_RETURN(local_t); } @@ -1296,9 +1342,24 @@ Time_zone_offset::Time_zone_offset(long tz_offset_arg): my_time_t Time_zone_offset::TIME_to_gmt_sec(const TIME *t, my_bool *in_dst_time_gap) const { - return sec_since_epoch(t->year, t->month, t->day, - t->hour, t->minute, t->second) - - offset; + my_time_t local_t; + + /* + Check timestamp range.we have to do this as calling function relies on + us to make all validation checks here. + */ + if (!validate_timestamp_range(t)) + return 0; + + local_t= sec_since_epoch(t->year, t->month, t->day, + t->hour, t->minute, t->second) - + offset; + + if (local_t >= TIMESTAMP_MIN_VALUE && local_t <= TIMESTAMP_MAX_VALUE) + return local_t; + + /* range error*/ + return 0; } |