Commit c293f037 authored by MySQL Build Team's avatar MySQL Build Team

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.)
parent 0d3f2543
...@@ -341,4 +341,18 @@ ta_y s tb_y s ...@@ -341,4 +341,18 @@ ta_y s tb_y s
2001 2001 2001 2001 2001 2001 2001 2001
DROP TABLE t1; 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 End of 5.1 tests
...@@ -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 ...@@ -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; 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 #
--echo End of 5.1 tests --echo End of 5.1 tests
...@@ -2960,11 +2960,10 @@ class Item_cache: public Item_basic_constant ...@@ -2960,11 +2960,10 @@ class Item_cache: public Item_basic_constant
protected: protected:
Item *example; Item *example;
table_map used_table_map; 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 index-based subquery engines to detect and remove the equality injected
by IN->EXISTS transformation. by IN->EXISTS transformation.
For all other uses of Item_cache, cached_field doesn't matter.
*/ */
Field *cached_field; Field *cached_field;
enum enum_field_types cached_field_type; enum enum_field_types cached_field_type;
...@@ -3021,6 +3020,14 @@ class Item_cache: public Item_basic_constant ...@@ -3021,6 +3020,14 @@ class Item_cache: public Item_basic_constant
{ {
return this == item; 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 void store(Item *item);
virtual bool cache_value()= 0; virtual bool cache_value()= 0;
}; };
......
...@@ -1196,9 +1196,12 @@ get_year_value(THD *thd, Item ***item_arg, Item **cache_arg, ...@@ -1196,9 +1196,12 @@ get_year_value(THD *thd, Item ***item_arg, Item **cache_arg,
value of 2000. value of 2000.
*/ */
Item *real_item= item->real_item(); Item *real_item= item->real_item();
if (!(real_item->type() == Item::FIELD_ITEM && Field *field= NULL;
((Item_field *)real_item)->field->type() == MYSQL_TYPE_YEAR && if (real_item->type() == Item::FIELD_ITEM)
((Item_field *)real_item)->field->field_length == 4)) 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) if (value < 70)
value+= 100; value+= 100;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment