Bug#28133: Wrong DATE/DATETIME comparison in IN() function.

The IN function was comparing DATE/DATETIME values either as ints or as
strings. Both methods have their disadvantages and may lead to a wrong
result.

Now IN function checks whether all of its arguments has the STRING result
types and at least one of them is a DATE/DATETIME item. If so it uses either
an object of the in_datetime class or an object of the cmp_item_datetime
class to perform its work. If the IN() function arguments are rows then
row columns are checked whether the DATE/DATETIME comparator should be used
to compare them.
The in_datetime class is used to find occurence of the item to be checked
in the vector of the constant DATE/DATETIME values. The cmp_item_datetime
class is used to compare items one by one in the DATE/DATETIME context.
Both classes obtain values from items with help of the get_datetime_value()
function and cache the left item if it is a constant one.



mysql-test/t/type_datetime.test:
  Added a test case for the bug#28133: Wrong DATE/DATETIME comparison in IN() function.
mysql-test/r/type_datetime.result:
  Added a test case for the bug#28133: Wrong DATE/DATETIME comparison in IN() function.
mysql-test/r/func_in.result:
  A test case result is corrected after the fix for the bug#28133.
sql/item_cmpfunc.h:
  Bug#28133: Wrong DATE/DATETIME comparison in IN() function.
  Two DATE/DATETIME comparison classes are added.
  The in_datetime class is used to find occurence of the item to be checked
  in the vector of the constant DATE/DATETIME values. The cmp_item_datetime
  class is used to compare items one by one in the DATE/DATETIME context.
  Both classes obtain values from items with help of the get_datetime_value()
  function and cache the left item if it is a constant one.
sql/item_cmpfunc.cc:
  Bug#28133: Wrong DATE/DATETIME comparison in IN() function.
  Now IN function checks whether all of its arguments has the STRING result
  types and at least one of them is a DATE/DATETIME item. If so it uses either
  an object of the in_datetime class or an object of the cmp_item_datetime
  class to perform its work. If the IN() function arguments are rows then
  row columns are checked whether the DATE/DATETIME comparator should be used
  to compare them.
This commit is contained in:
unknown 2007-05-07 22:20:43 +04:00
commit 0fd2b3ddc6
5 changed files with 351 additions and 71 deletions

View file

@ -833,6 +833,7 @@ public:
class in_longlong :public in_vector
{
protected:
/*
Here we declare a temporary variable (tmp) of the same type as the
elements of this vector. tmp is used in finding if a given value is in
@ -866,6 +867,30 @@ public:
friend int cmp_longlong(void *cmp_arg, packed_longlong *a,packed_longlong *b);
};
/*
Class to represent a vector of constant DATE/DATETIME values.
Values are obtained with help of the get_datetime_value() function.
If the left item is a constant one then its value is cached in the
lval_cache variable.
*/
class in_datetime :public in_longlong
{
public:
THD *thd;
/* An item used to issue warnings. */
Item *warn_item;
/* Cache for the left item. */
Item *lval_cache;
in_datetime(Item *warn_item_arg, uint elements)
:in_longlong(elements), thd(current_thd), warn_item(warn_item_arg),
lval_cache(0) {};
void set(uint pos,Item *item);
byte *get_value(Item *item);
friend int cmp_longlong(void *cmp_arg, packed_longlong *a,packed_longlong *b);
};
class in_double :public in_vector
{
double tmp;
@ -986,6 +1011,30 @@ public:
cmp_item *make_same();
};
/*
Compare items in the DATETIME context.
Values are obtained with help of the get_datetime_value() function.
If the left item is a constant one then its value is cached in the
lval_cache variable.
*/
class cmp_item_datetime :public cmp_item
{
ulonglong value;
public:
THD *thd;
/* Item used for issuing warnings. */
Item *warn_item;
/* Cache for the left item. */
Item *lval_cache;
cmp_item_datetime(Item *warn_item_arg)
:thd(current_thd), warn_item(warn_item_arg), lval_cache(0) {}
void store_value(Item *item);
int cmp(Item *arg);
int compare(cmp_item *ci);
cmp_item *make_same();
};
class cmp_item_real :public cmp_item
{
double value;
@ -1020,31 +1069,6 @@ public:
};
class cmp_item_row :public cmp_item
{
cmp_item **comparators;
uint n;
public:
cmp_item_row(): comparators(0), n(0) {}
~cmp_item_row();
void store_value(Item *item);
int cmp(Item *arg);
int compare(cmp_item *arg);
cmp_item *make_same();
void store_value_by_template(cmp_item *tmpl, Item *);
};
class in_row :public in_vector
{
cmp_item_row tmp;
public:
in_row(uint elements, Item *);
~in_row();
void set(uint pos,Item *item);
byte *get_value(Item *item);
};
/*
cmp_item for optimized IN with row (right part string, which never
be changed)
@ -1120,6 +1144,34 @@ public:
CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
};
class cmp_item_row :public cmp_item
{
cmp_item **comparators;
uint n;
public:
cmp_item_row(): comparators(0), n(0) {}
~cmp_item_row();
void store_value(Item *item);
inline void alloc_comparators();
int cmp(Item *arg);
int compare(cmp_item *arg);
cmp_item *make_same();
void store_value_by_template(cmp_item *tmpl, Item *);
friend void Item_func_in::fix_length_and_dec();
};
class in_row :public in_vector
{
cmp_item_row tmp;
public:
in_row(uint elements, Item *);
~in_row();
void set(uint pos,Item *item);
byte *get_value(Item *item);
friend void Item_func_in::fix_length_and_dec();
};
/* Functions used by where clause */
class Item_func_isnull :public Item_bool_func