From 651313bf91d7771831de7228bb4130f0ac64c33a Mon Sep 17 00:00:00 2001 From: Oystein Grovlen Date: Wed, 12 Jan 2011 10:37:15 +0100 Subject: [PATCH] Bug#59211: Select Returns Different Value for min(year) Function get_year_value() contains code to convert 2-digits year to 4-digits. The fix for Bug#49910 added a check on the size of the underlying field so that this conversion is not done for YEAR(4) values. (Since otherwise one would convert invalid YEAR(4) values to valid ones.) The existing check does not work when Item_cache is used, since it is not detected when the cache is based on a Field. The reported change in behavior is due to Bug#58030 which added extra cached items in min/max computations. The elegant solution would be to implement Item_cache::real_item() to return the underlying Item. However, some side effects are observed (change in explain output) that indicates that such a change is not straight- forward, and definitely not appropriate for an MRU. Instead, a Item_cache::field() method has been added in order to get access to the underlying field. (This field() method eliminates the need for Item_cache::eq_def() used in test_if_ref(), but in order to limit the scope of this fix, that code has been left as is.) mysql-test/r/type_year.result: Added test case for Bug#59211. mysql-test/t/type_year.test: Added test case for Bug#59211. sql/item.h: Added function Item_cache::field() to get access to the underlying Field of a cached field Value. sql/item_cmpfunc.cc: Also check underlying fields of Item_cache, not just Item_Field, when checking whether the value is of type YEAR(4) or not. --- mysql-test/r/type_year.result | 14 ++++++++++++++ mysql-test/t/type_year.test | 10 ++++++++++ sql/item.h | 13 ++++++++++--- sql/item_cmpfunc.cc | 9 ++++++--- 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/type_year.result b/mysql-test/r/type_year.result index 8948214f565..2dc491c6166 100644 --- a/mysql-test/r/type_year.result +++ b/mysql-test/r/type_year.result @@ -341,4 +341,18 @@ ta_y s tb_y s 2001 2001 2001 2001 DROP TABLE t1; # +# Bug #59211: Select Returns Different Value for min(year) Function +# +CREATE TABLE t1(c1 YEAR(4)); +INSERT INTO t1 VALUES (1901),(2155),(0000); +SELECT * FROM t1; +c1 +1901 +2155 +0000 +SELECT COUNT(*) AS total_rows, MIN(c1) AS min_value, MAX(c1) FROM t1; +total_rows min_value MAX(c1) +3 0 2155 +DROP TABLE t1; +# End of 5.1 tests diff --git a/mysql-test/t/type_year.test b/mysql-test/t/type_year.test index d8da4ccc82c..1a9e66478e1 100644 --- a/mysql-test/t/type_year.test +++ b/mysql-test/t/type_year.test @@ -149,6 +149,16 @@ SELECT ta.y AS ta_y, ta.s, tb.y AS tb_y, tb.s FROM t1 ta, t1 tb HAVING ta_y = tb DROP TABLE t1; +--echo # +--echo # Bug #59211: Select Returns Different Value for min(year) Function +--echo # + +CREATE TABLE t1(c1 YEAR(4)); +INSERT INTO t1 VALUES (1901),(2155),(0000); +SELECT * FROM t1; +SELECT COUNT(*) AS total_rows, MIN(c1) AS min_value, MAX(c1) FROM t1; +DROP TABLE t1; + --echo # --echo End of 5.1 tests diff --git a/sql/item.h b/sql/item.h index eb809ca410f..fdf8d4906d1 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2960,11 +2960,10 @@ class Item_cache: public Item_basic_constant protected: Item *example; table_map used_table_map; - /* - Field that this object will get value from. This is set/used by + /** + Field that this object will get value from. This is used by index-based subquery engines to detect and remove the equality injected by IN->EXISTS transformation. - For all other uses of Item_cache, cached_field doesn't matter. */ Field *cached_field; enum enum_field_types cached_field_type; @@ -3021,6 +3020,14 @@ public: { return this == item; } + + /** + If this item caches a field value, return pointer to underlying field. + + @return Pointer to field, or NULL if this is not a cache for a field value. + */ + Field* field() { return cached_field; } + virtual void store(Item *item); virtual bool cache_value()= 0; }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index d2e1ebbb3a1..4f2034ae902 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1196,9 +1196,12 @@ get_year_value(THD *thd, Item ***item_arg, Item **cache_arg, value of 2000. */ Item *real_item= item->real_item(); - if (!(real_item->type() == Item::FIELD_ITEM && - ((Item_field *)real_item)->field->type() == MYSQL_TYPE_YEAR && - ((Item_field *)real_item)->field->field_length == 4)) + Field *field= NULL; + if (real_item->type() == Item::FIELD_ITEM) + field= ((Item_field *)real_item)->field; + else if (real_item->type() == Item::CACHE_ITEM) + field= ((Item_cache *)real_item)->field(); + if (!(field && field->type() == MYSQL_TYPE_YEAR && field->field_length == 4)) { if (value < 70) value+= 100;