From: Tor Didriksen Date: January 14 2011 9:30am Subject: bzr push into mysql-trunk branch (tor.didriksen:3503 to 3504) Bug#59241 List-Archive: http://lists.mysql.com/commits/128704 X-Bug: 59241 Message-Id: <20110114093041.2189B3776@atum07.norway.sun.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3504 Tor Didriksen 2011-01-14 [merge] Merge Bug #59241 from 5.5 @ unittest/gunit/CMakeLists.txt New unit test. @ unittest/gunit/my_decimal-t.cc Unit test for my_decimal copy constructor and assignment operator. added: unittest/gunit/my_decimal-t.cc modified: mysql-test/r/func_math.result mysql-test/t/func_math.test sql/item_cmpfunc.cc sql/item_func.cc sql/my_decimal.h sql/sql_analyse.cc strings/decimal.c unittest/gunit/CMakeLists.txt 3503 Ole John Aske 2011-01-14 Fix for bug#58628: Incorrect result for 'WHERE NULL NOT IN () create_ref_for_key() allowed any constant part of a REF key to be evaluated and stored into the 'key_buff' during ::optimize(). These 'store_key*' was *not* kept in ref.key_copy[] as they where constant and we assumed we would not have to reevaluate them during JOIN::exec() However, during execute NULL values in REF key has to be detected as they may need special attention - as in 'Full scan on NULL key'. This is done by subselect_uniquesubquery_engine::copy_ref_key() which check if any keyparts evaluated to a NULL-value. As we didn't keep a store_key for a constant value, a NULL-constant was not detected by subselect_uniquesubquery_engine::copy_ref_key() ! This fixs modifies create_ref_for_key() to check if a NULL-value constant was produced - In these cases it keeps the store_key, which then will be reevaluated in JOIN::exec() and trigger correct handling of NULL-valued keys. @ mysql-test/r/update.result Update of result file due to changed (improved) behaviour when constructing a REF key from 'out of bound' values. As the main fix will cause failing const key value ::copy() to be reevaluate inside JOIN::exec(), we will detect out of bound values (which will form an illegal/undefined REF key) before executing the access request. Previously these const REF keys was produced by JOIN::optimize() and any conversion/range errors was ignored. - Possibly causing undefined keys to be produced. These access request may then be ignored wo/ a Handler_read_key request being executed. modified: mysql-test/include/func_in.inc mysql-test/r/func_in_icp.result mysql-test/r/func_in_icp_mrr.result mysql-test/r/func_in_mrr.result mysql-test/r/func_in_mrr_cost.result mysql-test/r/func_in_none.result mysql-test/r/update.result sql/sql_select.cc sql/sql_select.h === modified file 'mysql-test/r/func_math.result' --- a/mysql-test/r/func_math.result 2010-12-24 11:30:28 +0000 +++ b/mysql-test/r/func_math.result 2011-01-14 09:29:11 +0000 @@ -641,3 +641,12 @@ INSERT INTO t1 (SELECT -pi()); Warnings: Warning 1265 Data truncated for column 'a' at row 1 DROP TABLE t1; +# +# Bug #59241 invalid memory read +# in do_div_mod with doubly assigned variables +# +SELECT ((@a:=@b:=1.0) div (@b:=@a:=get_format(datetime, 'usa'))); +((@a:=@b:=1.0) div (@b:=@a:=get_format(datetime, 'usa'))) +NULL +Warnings: +Warning 1366 Incorrect decimal value: '' for column '' at row -1 === modified file 'mysql-test/t/func_math.test' --- a/mysql-test/t/func_math.test 2010-12-24 11:30:28 +0000 +++ b/mysql-test/t/func_math.test 2011-01-14 09:29:11 +0000 @@ -489,3 +489,9 @@ as foo; CREATE TABLE t1(a char(0)); INSERT INTO t1 (SELECT -pi()); DROP TABLE t1; + +--echo # +--echo # Bug #59241 invalid memory read +--echo # in do_div_mod with doubly assigned variables +--echo # +SELECT ((@a:=@b:=1.0) div (@b:=@a:=get_format(datetime, 'usa'))); === modified file 'sql/item_cmpfunc.cc' --- a/sql/item_cmpfunc.cc 2011-01-13 09:08:47 +0000 +++ b/sql/item_cmpfunc.cc 2011-01-14 09:29:11 +0000 @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2172,7 +2172,6 @@ void Item_func_interval::fix_length_and_ if (dec != &range->dec) { range->dec= *dec; - range->dec.fix_buffer_pointer(); } } else === modified file 'sql/item_func.cc' --- a/sql/item_func.cc 2010-12-29 00:38:59 +0000 +++ b/sql/item_func.cc 2011-01-14 09:29:11 +0000 @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1599,24 +1599,22 @@ longlong Item_func_int_div::val_int() if (args[0]->result_type() != INT_RESULT || args[1]->result_type() != INT_RESULT) { - my_decimal value0, value1, tmp; - my_decimal *val0, *val1; - longlong res; - int err; - - val0= args[0]->val_decimal(&value0); - val1= args[1]->val_decimal(&value1); + my_decimal tmp; + my_decimal val0= *args[0]->val_decimal(&tmp); + my_decimal val1= *args[1]->val_decimal(&tmp); if ((null_value= (args[0]->null_value || args[1]->null_value))) return 0; + int err; if ((err= my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, &tmp, - val0, val1, 0)) > 3) + &val0, &val1, 0)) > 3) { if (err == E_DEC_DIV_ZERO) signal_divide_by_null(); return 0; } + longlong res; if (my_decimal2int(E_DEC_FATAL_ERROR, &tmp, unsigned_flag, &res) & E_DEC_OVERFLOW) raise_integer_overflow(); === modified file 'sql/my_decimal.h' --- a/sql/my_decimal.h 2010-10-19 22:58:36 +0000 +++ b/sql/my_decimal.h 2011-01-14 09:29:11 +0000 @@ -1,4 +1,4 @@ -/* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -102,6 +102,24 @@ class my_decimal :public decimal_t public: + my_decimal(const my_decimal &rhs) : decimal_t(rhs) + { + for (uint i= 0; i < DECIMAL_BUFF_LENGTH; i++) + buffer[i]= rhs.buffer[i]; + fix_buffer_pointer(); + } + + my_decimal& operator=(const my_decimal &rhs) + { + if (this == &rhs) + return *this; + decimal_t::operator=(rhs); + for (uint i= 0; i < DECIMAL_BUFF_LENGTH; i++) + buffer[i]= rhs.buffer[i]; + fix_buffer_pointer(); + return *this; + } + void init() { len= DECIMAL_BUFF_LENGTH; @@ -248,7 +266,6 @@ inline void my_decimal2decimal(const my_decimal *from, my_decimal *to) { *to= *from; - to->fix_buffer_pointer(); } === modified file 'sql/sql_analyse.cc' --- a/sql/sql_analyse.cc 2010-07-16 21:00:50 +0000 +++ b/sql/sql_analyse.cc 2011-01-14 09:29:11 +0000 @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -521,9 +521,6 @@ void field_decimal::add() { found = 1; min_arg = max_arg = sum[0] = *dec; - min_arg.fix_buffer_pointer(); - max_arg.fix_buffer_pointer(); - sum[0].fix_buffer_pointer(); my_decimal_mul(E_DEC_FATAL_ERROR, sum_sqr, dec, dec); cur_sum= 0; min_length = max_length = length; @@ -545,12 +542,10 @@ void field_decimal::add() if (my_decimal_cmp(dec, &min_arg) < 0) { min_arg= *dec; - min_arg.fix_buffer_pointer(); } if (my_decimal_cmp(dec, &max_arg) > 0) { max_arg= *dec; - max_arg.fix_buffer_pointer(); } } } === modified file 'strings/decimal.c' --- a/strings/decimal.c 2010-07-20 19:30:10 +0000 +++ b/strings/decimal.c 2011-01-14 09:05:14 +0000 @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -13,8 +13,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#line 18 "decimal.c" - /* ======================================================================= NOTE: this library implements SQL standard "exact numeric" type === modified file 'unittest/gunit/CMakeLists.txt' --- a/unittest/gunit/CMakeLists.txt 2010-12-17 09:41:21 +0000 +++ b/unittest/gunit/CMakeLists.txt 2011-01-14 09:29:11 +0000 @@ -212,6 +212,7 @@ SET(TESTS dbug mdl mdl_mytap + my_decimal my_regex sql_list thread_utils === added file 'unittest/gunit/my_decimal-t.cc' --- a/unittest/gunit/my_decimal-t.cc 1970-01-01 00:00:00 +0000 +++ b/unittest/gunit/my_decimal-t.cc 2011-01-14 09:29:11 +0000 @@ -0,0 +1,57 @@ +/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "my_config.h" +#include + +#include + +namespace { + +class DecimalTest : public ::testing::Test +{ +protected: + my_decimal d1; + my_decimal d2; +}; + +TEST_F(DecimalTest, CopyAndCompare) +{ + ulonglong val= 42; + EXPECT_EQ(0, ulonglong2decimal(val, &d1)); + + d2= d1; // operator=() + my_decimal d3(d1); // Copy constructor. + + EXPECT_EQ(0, my_decimal_cmp(&d1, &d2)); + EXPECT_EQ(0, my_decimal_cmp(&d2, &d3)); + EXPECT_EQ(0, my_decimal_cmp(&d3, &d1)); + + ulonglong val1, val2, val3; + EXPECT_EQ(0, decimal2ulonglong(&d1, &val1)); + EXPECT_EQ(0, decimal2ulonglong(&d2, &val2)); + EXPECT_EQ(0, decimal2ulonglong(&d3, &val3)); + EXPECT_EQ(val, val1); + EXPECT_EQ(val, val2); + EXPECT_EQ(val, val3); + + // The CTOR/operator=() generated by the compiler would fail here: + val= 45; + EXPECT_EQ(0, ulonglong2decimal(val, &d1)); + EXPECT_EQ(1, my_decimal_cmp(&d1, &d2)); + EXPECT_EQ(1, my_decimal_cmp(&d1, &d3)); +} + +} No bundle (reason: useless for push emails).