Commit 651313bf authored by Oystein Grovlen's avatar Oystein Grovlen

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.
parent 83b4e920
......@@ -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
......@@ -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
......@@ -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;
};
......
......@@ -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;
......
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