diff options
author | MySQL Build Team <build@mysql.com> | 2011-02-09 21:15:36 +0100 |
---|---|---|
committer | MySQL Build Team <build@mysql.com> | 2011-02-09 21:15:36 +0100 |
commit | 9b656643810e858eea13fb0633d834580754ee46 (patch) | |
tree | 4281992519869b76bb4009f11e211add6139faed | |
parent | aee322264fd86dd503939cfcff906e00d73bad1c (diff) | |
download | mariadb-git-9b656643810e858eea13fb0633d834580754ee46.tar.gz |
Backport into build-201102032246-5.1.52sp1
> ------------------------------------------------------------
> revno: 3452.13.54
> revision-id: oystein.grovlen@oracle.com-20110112093715-tc076voaxwblqk8v
> parent: georgi.kodinov@oracle.com-20110110130833-1c9q21mr7zoq07vg
> committer: Oystein Grovlen <oystein.grovlen@oracle.com>
> branch nick: mysql-5.1-security
> timestamp: Wed 2011-01-12 10:37:15 +0100
> message:
> 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.)
-rw-r--r-- | mysql-test/r/type_year.result | 14 | ||||
-rw-r--r-- | mysql-test/t/type_year.test | 10 | ||||
-rw-r--r-- | sql/item.h | 13 | ||||
-rw-r--r-- | 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 @@ -150,5 +150,15 @@ 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 57abb43010e..fd85fc780af 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 6987dd9e053..8b8ee4a0054 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; |