Commit 95d075a0 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-15293 CAST(AS TIME) returns bad results for LAST_VALUE(),NAME_CONST(),SP variable

parent 0c4aeef9
......@@ -1487,3 +1487,45 @@ lt_minus200_implicit 200
lt_minus200_explictit 200
lt_plus200_implicit 10
lt_plus200_explicit 10
#
# MDEV-15293 CAST(AS TIME) returns bad results for LAST_VALUE(),NAME_CONST(),SP variable
#
SELECT CAST(DATE'2001-01-01' AS TIME);
CAST(DATE'2001-01-01' AS TIME)
00:00:00
SELECT CAST(LAST_VALUE(DATE'2001-01-01') AS TIME);
CAST(LAST_VALUE(DATE'2001-01-01') AS TIME)
00:00:00
SELECT CAST(NAME_CONST('name',DATE'2001-01-01') AS TIME);
CAST(NAME_CONST('name',DATE'2001-01-01') AS TIME)
00:00:00
BEGIN NOT ATOMIC
DECLARE a DATE DEFAULT '2001-01-01';
SELECT CAST(a AS TIME);
END;
$$
CAST(a AS TIME)
00:00:00
CREATE OR REPLACE TABLE t1 (dt DATE,country VARCHAR(10), amount INT);
INSERT INTO t1 VALUES ('2000-01-01','DE',102);
SELECT
dt, country, amount,
FIRST_VALUE(dt) OVER () AS first,
MINUTE(FIRST_VALUE(dt) OVER ()) AS m_first,
LAST_VALUE(dt) OVER () AS last,
MINUTE(LAST_VALUE(dt) OVER ()) AS m_last
FROM t1
ORDER BY country, dt;
dt country amount first m_first last m_last
2000-01-01 DE 102 2000-01-01 0 2000-01-01 0
SELECT
dt, country, amount,
FIRST_VALUE(dt) OVER () AS first,
CAST(FIRST_VALUE(dt) OVER () AS TIME) AS t_first,
LAST_VALUE(dt) OVER () AS last,
CAST(LAST_VALUE(dt) OVER () AS TIME) AS t_last
FROM t1
ORDER BY country, dt;
dt country amount first t_first last t_last
2000-01-01 DE 102 2000-01-01 00:00:00 2000-01-01 00:00:00
DROP TABLE t1;
......@@ -866,3 +866,39 @@ SELECT
HOUR(LEAST(CAST('2010-01-01 10:10:10' AS TIME(6)),TIME('200:20:20'))) AS lt_plus200_explicit;
--horizontal_results
--echo #
--echo # MDEV-15293 CAST(AS TIME) returns bad results for LAST_VALUE(),NAME_CONST(),SP variable
--echo #
SELECT CAST(DATE'2001-01-01' AS TIME);
SELECT CAST(LAST_VALUE(DATE'2001-01-01') AS TIME);
SELECT CAST(NAME_CONST('name',DATE'2001-01-01') AS TIME);
DELIMITER $$;
BEGIN NOT ATOMIC
DECLARE a DATE DEFAULT '2001-01-01';
SELECT CAST(a AS TIME);
END;
$$
DELIMITER ;$$
CREATE OR REPLACE TABLE t1 (dt DATE,country VARCHAR(10), amount INT);
INSERT INTO t1 VALUES ('2000-01-01','DE',102);
SELECT
dt, country, amount,
FIRST_VALUE(dt) OVER () AS first,
MINUTE(FIRST_VALUE(dt) OVER ()) AS m_first,
LAST_VALUE(dt) OVER () AS last,
MINUTE(LAST_VALUE(dt) OVER ()) AS m_last
FROM t1
ORDER BY country, dt;
SELECT
dt, country, amount,
FIRST_VALUE(dt) OVER () AS first,
CAST(FIRST_VALUE(dt) OVER () AS TIME) AS t_first,
LAST_VALUE(dt) OVER () AS last,
CAST(LAST_VALUE(dt) OVER () AS TIME) AS t_last
FROM t1
ORDER BY country, dt;
DROP TABLE t1;
......@@ -1454,67 +1454,73 @@ Item *Item_param::safe_charset_converter(THD *thd, CHARSET_INFO *tocs)
As a extra convenience the time structure is reset on error or NULL values!
*/
bool Item::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate)
bool Item::get_date_from_int(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
if (field_type() == MYSQL_TYPE_TIME)
fuzzydate|= TIME_TIME_ONLY;
longlong value= val_int();
bool neg= !unsigned_flag && value < 0;
if (null_value || int_to_datetime_with_warn(neg, neg ? -value : value,
ltime, fuzzydate,
field_name_or_null()))
return null_value|= make_zero_date(ltime, fuzzydate);
return null_value= false;
}
switch (result_type()) {
case INT_RESULT:
{
longlong value= val_int();
bool neg= !unsigned_flag && value < 0;
if (field_type() == MYSQL_TYPE_YEAR)
{
if (max_length == 2)
{
if (value < 70)
value+= 2000;
else if (value <= 1900)
value+= 1900;
}
value*= 10000; /* make it YYYYMMHH */
}
if (null_value || int_to_datetime_with_warn(neg, neg ? -value : value,
ltime, fuzzydate,
field_name_or_null()))
goto err;
break;
}
case REAL_RESULT:
{
double value= val_real();
if (null_value || double_to_datetime_with_warn(value, ltime, fuzzydate,
field_name_or_null()))
goto err;
break;
}
case DECIMAL_RESULT:
{
my_decimal value, *res;
if (!(res= val_decimal(&value)) ||
decimal_to_datetime_with_warn(res, ltime, fuzzydate,
field_name_or_null()))
goto err;
break;
}
case STRING_RESULT:
bool Item::get_date_from_year(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
longlong value= val_int();
DBUG_ASSERT(unsigned_flag || value >= 0);
if (max_length == 2)
{
char buff[40];
String tmp(buff,sizeof(buff), &my_charset_bin),*res;
if (!(res=val_str(&tmp)) ||
str_to_datetime_with_warn(res->charset(), res->ptr(), res->length(),
ltime, fuzzydate))
goto err;
break;
}
default:
DBUG_ASSERT(0);
if (value < 70)
value+= 2000;
else if (value <= 1900)
value+= 1900;
}
value*= 10000; /* make it YYYYMMHH */
if (null_value || int_to_datetime_with_warn(false, value,
ltime, fuzzydate,
field_name_or_null()))
return null_value|= make_zero_date(ltime, fuzzydate);
return null_value= false;
}
return null_value= 0;
err:
bool Item::get_date_from_real(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
double value= val_real();
if (null_value || double_to_datetime_with_warn(value, ltime, fuzzydate,
field_name_or_null()))
return null_value|= make_zero_date(ltime, fuzzydate);
return null_value= false;
}
bool Item::get_date_from_decimal(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
my_decimal value, *res;
if (!(res= val_decimal(&value)) ||
decimal_to_datetime_with_warn(res, ltime, fuzzydate,
field_name_or_null()))
return null_value|= make_zero_date(ltime, fuzzydate);
return null_value= false;
}
bool Item::get_date_from_string(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
char buff[40];
String tmp(buff,sizeof(buff), &my_charset_bin),*res;
if (!(res=val_str(&tmp)) ||
str_to_datetime_with_warn(res->charset(), res->ptr(), res->length(),
ltime, fuzzydate))
return null_value|= make_zero_date(ltime, fuzzydate);
return null_value= false;
}
bool Item::make_zero_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
/*
if the item was not null and convertion failed, we return a zero date
if allowed, otherwise - null.
......@@ -1536,7 +1542,7 @@ bool Item::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate)
*/
ltime->time_type= MYSQL_TIMESTAMP_TIME;
}
return null_value|= !(fuzzydate & TIME_FUZZY_DATES);
return !(fuzzydate & TIME_FUZZY_DATES);
}
bool Item::get_seconds(ulonglong *sec, ulong *sec_part)
......@@ -1780,6 +1786,16 @@ my_decimal *Item_sp_variable::val_decimal(my_decimal *decimal_value)
}
bool Item_sp_variable::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
DBUG_ASSERT(fixed);
Item *it= this_item();
bool val= it->get_date(ltime, fuzzydate);
null_value= it->null_value;
return val;
}
bool Item_sp_variable::is_null()
{
return this_item()->is_null();
......@@ -2125,6 +2141,13 @@ my_decimal *Item_name_const::val_decimal(my_decimal *decimal_value)
return val;
}
bool Item_name_const::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
DBUG_ASSERT(fixed);
bool rc= value_item->get_date(ltime, fuzzydate);
null_value= value_item->null_value;
return rc;
}
bool Item_name_const::is_null()
{
......@@ -3731,6 +3754,15 @@ my_decimal *Item_null::val_decimal(my_decimal *decimal_value)
}
bool Item_null::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
// following assert is redundant, because fixed=1 assigned in constructor
DBUG_ASSERT(fixed == 1);
make_zero_date(ltime, fuzzydate);
return (null_value= true);
}
Item *Item_null::safe_charset_converter(THD *thd, CHARSET_INFO *tocs)
{
return this;
......@@ -4201,7 +4233,7 @@ bool Item_param::get_date(MYSQL_TIME *res, ulonglong fuzzydate)
*res= value.time;
return 0;
}
return Item::get_date(res, fuzzydate);
return type_handler()->Item_get_date(this, res, fuzzydate);
}
......@@ -10191,6 +10223,12 @@ String *Item_type_holder::val_str(String*)
return 0;
}
bool Item_type_holder::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
DBUG_ASSERT(0); // should never be called
return true;
}
void Item_result_field::cleanup()
{
DBUG_ENTER("Item_result_field::cleanup()");
......
......@@ -672,6 +672,12 @@ class Item: public Value_source,
DBUG_ASSERT(fixed == 1);
return (null_value= item->get_date_with_conversion(ltime, fuzzydate));
}
/*
This method is used if the item was not null but convertion to
TIME/DATE/DATETIME failed. We return a zero date if allowed,
otherwise - null.
*/
bool make_zero_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
public:
/*
......@@ -1350,7 +1356,12 @@ class Item: public Value_source,
void split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array,
List<Item> &fields,
Item **ref, uint flags);
virtual bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
virtual bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)= 0;
bool get_date_from_int(MYSQL_TIME *ltime, ulonglong fuzzydate);
bool get_date_from_year(MYSQL_TIME *ltime, ulonglong fuzzydate);
bool get_date_from_real(MYSQL_TIME *ltime, ulonglong fuzzydate);
bool get_date_from_decimal(MYSQL_TIME *ltime, ulonglong fuzzydate);
bool get_date_from_string(MYSQL_TIME *ltime, ulonglong fuzzydate);
bool get_time(MYSQL_TIME *ltime)
{ return get_date(ltime, TIME_TIME_ONLY | TIME_INVALID_DATES); }
// Get date with automatic TIME->DATETIME conversion
......@@ -2306,6 +2317,7 @@ class Item_sp_variable :public Item
longlong val_int();
String *val_str(String *sp);
my_decimal *val_decimal(my_decimal *decimal_value);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
bool is_null();
public:
......@@ -2568,6 +2580,7 @@ class Item_name_const : public Item
longlong val_int();
String *val_str(String *sp);
my_decimal *val_decimal(my_decimal *);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
bool is_null();
virtual void print(String *str, enum_query_type query_type);
......@@ -2604,6 +2617,10 @@ class Item_num: public Item_basic_constant
Item_num(THD *thd): Item_basic_constant(thd) { collation.set_numeric(); }
Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs);
bool check_partition_func_processor(void *int_arg) { return FALSE;}
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
return type_handler()->Item_get_date(this, ltime, fuzzydate);
}
};
#define NO_CACHED_FIELD_INDEX ((uint)(-1))
......@@ -2725,6 +2742,10 @@ class Item_ident_for_show :public Item
longlong val_int() { return field->val_int(); }
String *val_str(String *str) { return field->val_str(str); }
my_decimal *val_decimal(my_decimal *dec) { return field->val_decimal(dec); }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
return field->get_date(ltime, fuzzydate);
}
void make_field(THD *thd, Send_field *tmp_field);
const Type_handler *type_handler() const
{
......@@ -3025,6 +3046,7 @@ class Item_null :public Item_basic_constant
longlong val_int();
String *val_str(String *str);
my_decimal *val_decimal(my_decimal *);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
int save_in_field(Field *field, bool no_conversions);
int save_safe_in_field(Field *field);
bool send(Protocol *protocol, st_value *buffer);
......@@ -3735,6 +3757,10 @@ class Item_string :public Item_basic_constant
return (String*) &str_value;
}
my_decimal *val_decimal(my_decimal *);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
return get_date_from_string(ltime, fuzzydate);
}
int save_in_field(Field *field, bool no_conversions);
const Type_handler *type_handler() const { return &type_handler_varchar; }
bool basic_const_item() const { return 1; }
......@@ -4022,6 +4048,10 @@ class Item_hex_constant: public Item_basic_constant
str_value.bin_eq(&((Item_hex_constant*)item)->str_value);
}
String *val_str(String*) { DBUG_ASSERT(fixed == 1); return &str_value; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
return type_handler()->Item_get_date(this, ltime, fuzzydate);
}
};
......@@ -5324,6 +5354,8 @@ class Item_copy_string : public Item_copy
my_decimal *val_decimal(my_decimal *);
double val_real();
longlong val_int();
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return get_date_from_string(ltime, fuzzydate); }
void copy();
int save_in_field(Field *field, bool no_conversions);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
......@@ -5349,6 +5381,8 @@ class Item_copy_int : public Item_copy
{
return null_value ? 0 : cached_value;
}
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return get_date_from_int(ltime, fuzzydate); }
virtual void copy();
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_copy_int>(thd, mem_root, this); }
......@@ -5391,6 +5425,10 @@ class Item_copy_float : public Item_copy
{
return (longlong) rint(val_real());
}
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
return get_date_from_real(ltime, fuzzydate);
}
void copy()
{
cached_value= item->val_real();
......@@ -5416,6 +5454,10 @@ class Item_copy_decimal : public Item_copy
}
double val_real();
longlong val_int();
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
return get_date_from_decimal(ltime, fuzzydate);
}
void copy();
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_copy_decimal>(thd, mem_root, this); }
......@@ -5909,6 +5951,8 @@ class Item_cache_int: public Item_cache
longlong val_int();
String* val_str(String *str);
my_decimal *val_decimal(my_decimal *);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return get_date_from_int(ltime, fuzzydate); }
bool cache_value();
int save_in_field(Field *field, bool no_conversions);
Item *convert_to_basic_const_item(THD *thd);
......@@ -5917,6 +5961,15 @@ class Item_cache_int: public Item_cache
};
class Item_cache_year: public Item_cache_int
{
public:
Item_cache_year(THD *thd): Item_cache_int(thd, &type_handler_year) { }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return get_date_from_year(ltime, fuzzydate); }
};
class Item_cache_temporal: public Item_cache_int
{
protected:
......@@ -5984,6 +6037,8 @@ class Item_cache_real: public Item_cache
longlong val_int();
String* val_str(String *str);
my_decimal *val_decimal(my_decimal *);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return get_date_from_real(ltime, fuzzydate); }
bool cache_value();
Item *convert_to_basic_const_item(THD *thd);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
......@@ -6002,6 +6057,8 @@ class Item_cache_decimal: public Item_cache
longlong val_int();
String* val_str(String *str);
my_decimal *val_decimal(my_decimal *);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return get_date_from_decimal(ltime, fuzzydate); }
bool cache_value();
Item *convert_to_basic_const_item(THD *thd);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
......@@ -6028,6 +6085,8 @@ class Item_cache_str: public Item_cache
longlong val_int();
String* val_str(String *);
my_decimal *val_decimal(my_decimal *);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return get_date_from_string(ltime, fuzzydate); }
CHARSET_INFO *charset() const { return value->charset(); };
int save_in_field(Field *field, bool no_conversions);
bool cache_value();
......@@ -6108,6 +6167,11 @@ class Item_cache_row: public Item_cache
illegal_method_call((const char*)"val_decimal");
return 0;
};
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
illegal_method_call((const char*)"val_decimal");
return true;
}
uint cols() const { return item_count; }
Item *element_index(uint i) { return values[i]; }
......@@ -6186,6 +6250,7 @@ class Item_type_holder: public Item,
longlong val_int();
my_decimal *val_decimal(my_decimal *);
String *val_str(String*);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
Field *create_tmp_field(bool group, TABLE *table)
{
return Item_type_holder::real_type_handler()->
......
......@@ -5551,6 +5551,13 @@ my_decimal* Item_user_var_as_out_param::val_decimal(my_decimal *decimal_buffer)
}
bool Item_user_var_as_out_param::get_date(MYSQL_TIME *ltime, ulonglong fuzzy)
{
DBUG_ASSERT(0);
return true;
}
void Item_user_var_as_out_param::print_for_load(THD *thd, String *str)
{
str->append('@');
......@@ -6784,6 +6791,15 @@ my_decimal *Item_func_last_value::val_decimal(my_decimal *decimal_value)
}
bool Item_func_last_value::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
evaluate_sideeffects();
bool tmp= last_value->get_date(ltime, fuzzydate);
null_value= last_value->null_value;
return tmp;
}
void Item_func_last_value::fix_length_and_dec()
{
last_value= args[arg_count -1];
......
......@@ -386,6 +386,8 @@ class Item_real_func :public Item_func
my_decimal *val_decimal(my_decimal *decimal_value);
longlong val_int()
{ DBUG_ASSERT(fixed == 1); return (longlong) rint(val_real()); }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return get_date_from_real(ltime, fuzzydate); }
const Type_handler *type_handler() const { return &type_handler_double; }
void fix_length_and_dec()
{ decimals= NOT_FIXED_DEC; max_length= float_length(decimals); }
......@@ -755,6 +757,8 @@ class Item_int_func :public Item_func
{ collation.set_numeric(); }
double val_real();
String *val_str(String*str);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return get_date_from_int(ltime, fuzzydate); }
const Type_handler *type_handler() const= 0;
void fix_length_and_dec() {}
};
......@@ -948,6 +952,8 @@ class Item_decimal_typecast :public Item_func
double val_real();
longlong val_int();
my_decimal *val_decimal(my_decimal*);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return get_date_from_decimal(ltime, fuzzydate); }
const Type_handler *type_handler() const { return &type_handler_newdecimal; }
void fix_length_and_dec_generic() {}
void fix_length_and_dec()
......@@ -1591,6 +1597,10 @@ class Item_func_rollup_const :public Item_func
longlong val_int() { return args[0]->val_int(); }
String *val_str(String *str) { return args[0]->val_str(str); }
my_decimal *val_decimal(my_decimal *dec) { return args[0]->val_decimal(dec); }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
return args[0]->get_date(ltime, fuzzydate);
}
const char *func_name() const { return "rollup_const"; }
bool const_item() const { return 0; }
const Type_handler *type_handler() const { return args[0]->type_handler(); }
......@@ -2033,6 +2043,10 @@ class Item_udf_func :public Item_func
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_NON_DETERMINISTIC);
}
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
return type_handler()->Item_get_date(this, ltime, fuzzydate);
}
};
......@@ -2330,6 +2344,8 @@ class Item_func_user_var :public Item_hybrid_func
Field *create_field_for_create_select(TABLE *table)
{ return create_table_field_from_handler(table); }
bool check_vcol_func_processor(void *arg);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return type_handler()->Item_get_date(this, ltime, fuzzydate); }
};
......@@ -2473,6 +2489,7 @@ class Item_user_var_as_out_param :public Item
double val_real();
longlong val_int();
String *val_str(String *str);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
my_decimal *val_decimal(my_decimal *decimal_buffer);
/* fix_fields() binds variable name with its entry structure */
bool fix_fields(THD *thd, Item **ref);
......@@ -2520,6 +2537,10 @@ class Item_func_get_system_var :public Item_func
String* val_str(String*);
my_decimal *val_decimal(my_decimal *dec_buf)
{ return val_decimal_from_real(dec_buf); }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
return type_handler()->Item_get_date(this, ltime, fuzzydate);
}
/* TODO: fix to support views */
const char *func_name() const { return "get_system_var"; }
/**
......@@ -2971,6 +2992,7 @@ class Item_func_last_value :public Item_func
longlong val_int();
String *val_str(String *);
my_decimal *val_decimal(my_decimal *);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
void fix_length_and_dec();
const char *func_name() const { return "last_value"; }
const Type_handler *type_handler() const { return last_value->type_handler(); }
......
......@@ -82,6 +82,11 @@ class Item_row: public Item,
illegal_method_call((const char*)"val_decimal");
return 0;
};
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
illegal_method_call((const char*)"get_date");
return true;
}
bool fix_fields(THD *thd, Item **ref);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
void cleanup();
......
......@@ -62,6 +62,8 @@ class Item_str_func :public Item_func
longlong val_int();
double val_real();
my_decimal *val_decimal(my_decimal *);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return get_date_from_string(ltime, fuzzydate); }
const Type_handler *type_handler() const { return string_type_handler(); }
void left_right_max_length();
bool fix_fields(THD *thd, Item **ref);
......
......@@ -400,6 +400,8 @@ class Item_exists_subselect :public Item_subselect
String *val_str(String*);
my_decimal *val_decimal(my_decimal *);
bool val_bool();
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return get_date_from_int(ltime, fuzzydate); }
bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
void print(String *str, enum_query_type query_type);
......
......@@ -732,6 +732,10 @@ class Item_sum_num :public Item_sum
longlong val_int() { return val_int_from_real(); /* Real as default */ }
String *val_str(String*str);
my_decimal *val_decimal(my_decimal *);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
return type_handler()->Item_get_date(this, ltime, fuzzydate);
}
void reset_field();
};
......@@ -1227,6 +1231,10 @@ class Item_sum_field :public Item
{
return mark_unsupported_function(name.str, arg, VCOL_IMPOSSIBLE);
}
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
return type_handler()->Item_get_date(this, ltime, fuzzydate);
}
};
......@@ -1376,6 +1384,10 @@ class Item_udf_sum : public Item_sum
void update_field() {};
void cleanup();
virtual void print(String *str, enum_query_type query_type);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
return type_handler()->Item_get_date(this, ltime, fuzzydate);
}
};
......@@ -1661,6 +1673,10 @@ class Item_func_group_concat : public Item_sum
{
return val_decimal_from_string(decimal_value);
}
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
return get_date_from_string(ltime, fuzzydate);
}
String* val_str(String* str);
Item *copy_or_same(THD* thd);
void no_rows_in_result() {}
......
......@@ -181,6 +181,10 @@ class Item_func_month :public Item_func
str->set(nr, collation.collation);
return str;
}
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
return get_date_from_int(ltime, fuzzydate);
}
const char *func_name() const { return "month"; }
const Type_handler *type_handler() const { return &type_handler_long; }
void fix_length_and_dec()
......@@ -441,6 +445,10 @@ class Item_func_weekday :public Item_func
{
return (odbc_type ? "dayofweek" : "weekday");
}
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
return type_handler()->Item_get_date(this, ltime, fuzzydate);
}
const Type_handler *type_handler() const { return &type_handler_long; }
void fix_length_and_dec()
{
......
......@@ -344,6 +344,17 @@ Item_sum_hybrid_simple::val_str(String *str)
return retval;
}
bool Item_sum_hybrid_simple::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
DBUG_ASSERT(fixed == 1);
if (null_value)
return 0;
bool retval= value->get_date(ltime, fuzzydate);
if ((null_value= value->null_value))
DBUG_ASSERT(retval == true);
return retval;
}
Field *Item_sum_hybrid_simple::create_tmp_field(bool group, TABLE *table)
{
DBUG_ASSERT(0);
......
......@@ -303,6 +303,7 @@ class Item_sum_hybrid_simple : public Item_sum,
my_decimal *val_decimal(my_decimal *);
void reset_field();
String *val_str(String *);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
const Type_handler *type_handler() const
{ return Type_handler_hybrid_field_type::type_handler(); }
void update_field();
......@@ -938,6 +939,29 @@ class Item_window_func : public Item_func_or_sum
return res;
}
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
bool res;
if (force_return_blank)
{
null_value= true;
res= true;
}
else if (read_value_from_result_field)
{
if ((null_value= result_field->is_null()))
res= true;
else
res= result_field->get_date(ltime, fuzzydate);
}
else
{
res= window_func()->get_date(ltime, fuzzydate);
null_value= window_func()->null_value;
}
return res;
}
void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
List<Item> &fields, uint flags);
......
......@@ -59,6 +59,10 @@ class Item_proc :public Item
DBUG_ASSERT(0); // impossible
return mark_unsupported_function("proc", arg, VCOL_IMPOSSIBLE);
}
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
return type_handler()->Item_get_date(this, ltime, fuzzydate);
}
Item* get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; }
};
......
......@@ -2651,6 +2651,12 @@ Type_handler_int_result::Item_get_cache(THD *thd, const Item *item) const
return new (thd->mem_root) Item_cache_int(thd, item->type_handler());
}
Item_cache *
Type_handler_year::Item_get_cache(THD *thd, const Item *item) const
{
return new (thd->mem_root) Item_cache_year(thd);
}
Item_cache *
Type_handler_real_result::Item_get_cache(THD *thd, const Item *item) const
{
......@@ -3175,6 +3181,53 @@ bool Type_handler_string_result::Item_val_bool(Item *item) const
}
/*************************************************************************/
bool Type_handler_int_result::Item_get_date(Item *item, MYSQL_TIME *ltime,
ulonglong fuzzydate) const
{
return item->get_date_from_int(ltime, fuzzydate);
}
bool Type_handler_year::Item_get_date(Item *item, MYSQL_TIME *ltime,
ulonglong fuzzydate) const
{
return item->get_date_from_year(ltime, fuzzydate);
}
bool Type_handler_real_result::Item_get_date(Item *item, MYSQL_TIME *ltime,
ulonglong fuzzydate) const
{
return item->get_date_from_real(ltime, fuzzydate);
}
bool Type_handler_decimal_result::Item_get_date(Item *item, MYSQL_TIME *ltime,
ulonglong fuzzydate) const
{
return item->get_date_from_decimal(ltime, fuzzydate);
}
bool Type_handler_string_result::Item_get_date(Item *item, MYSQL_TIME *ltime,
ulonglong fuzzydate) const
{
return item->get_date_from_string(ltime, fuzzydate);
}
bool Type_handler_temporal_result::Item_get_date(Item *item, MYSQL_TIME *ltime,
ulonglong fuzzydate) const
{
DBUG_ASSERT(0); // Temporal type items must implement native get_date()
item->null_value= true;
set_zero_time(ltime, mysql_timestamp_type());
return true;
}
/*************************************************************************/
longlong Type_handler_real_result::
......@@ -3892,7 +3945,7 @@ bool Type_handler_string_result::
::get_date() can be called for non-temporal values,
for example, SELECT MONTH(GREATEST("2011-11-21", "2010-10-09"))
*/
return func->Item::get_date(ltime, fuzzydate);
return func->get_date_from_string(ltime, fuzzydate);
}
......@@ -3900,7 +3953,7 @@ bool Type_handler_numeric::
Item_func_min_max_get_date(Item_func_min_max *func,
MYSQL_TIME *ltime, ulonglong fuzzydate) const
{
return func->Item::get_date(ltime, fuzzydate);
return Item_get_date(func, ltime, fuzzydate);
}
......
......@@ -1026,6 +1026,8 @@ class Type_handler
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const= 0;
virtual bool Item_val_bool(Item *item) const= 0;
virtual bool Item_get_date(Item *item, MYSQL_TIME *ltime,
ulonglong fuzzydate) const= 0;
virtual longlong Item_val_int_signed_typecast(Item *item) const= 0;
virtual longlong Item_val_int_unsigned_typecast(Item *item) const= 0;
......@@ -1286,6 +1288,11 @@ class Type_handler_row: public Type_handler
DBUG_ASSERT(0);
return false;
}
bool Item_get_date(Item *item, MYSQL_TIME *ltime, ulonglong fuzzydate) const
{
DBUG_ASSERT(0);
return true;
}
longlong Item_val_int_signed_typecast(Item *item) const
{
DBUG_ASSERT(0);
......@@ -1492,6 +1499,7 @@ class Type_handler_real_result: public Type_handler_numeric
bool Item_func_signed_fix_length_and_dec(Item_func_signed *item) const;
bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const;
bool Item_val_bool(Item *item) const;
bool Item_get_date(Item *item, MYSQL_TIME *ltime, ulonglong fuzzydate) const;
longlong Item_val_int_signed_typecast(Item *item) const;
longlong Item_val_int_unsigned_typecast(Item *item) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
......@@ -1570,6 +1578,7 @@ class Type_handler_decimal_result: public Type_handler_numeric
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
bool Item_val_bool(Item *item) const;
bool Item_get_date(Item *item, MYSQL_TIME *ltime, ulonglong fuzzydate) const;
longlong Item_val_int_signed_typecast(Item *item) const;
longlong Item_val_int_unsigned_typecast(Item *item) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
......@@ -1638,6 +1647,7 @@ class Type_handler_int_result: public Type_handler_numeric
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
bool Item_val_bool(Item *item) const;
bool Item_get_date(Item *item, MYSQL_TIME *ltime, ulonglong fuzzydate) const;
longlong Item_val_int_signed_typecast(Item *item) const;
longlong Item_val_int_unsigned_typecast(Item *item) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
......@@ -1708,6 +1718,7 @@ class Type_handler_temporal_result: public Type_handler
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
bool Item_val_bool(Item *item) const;
bool Item_get_date(Item *item, MYSQL_TIME *ltime, ulonglong fuzzydate) const;
longlong Item_val_int_signed_typecast(Item *item) const;
longlong Item_val_int_unsigned_typecast(Item *item) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
......@@ -1821,6 +1832,7 @@ class Type_handler_string_result: public Type_handler
bool Item_func_signed_fix_length_and_dec(Item_func_signed *item) const;
bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const;
bool Item_val_bool(Item *item) const;
bool Item_get_date(Item *item, MYSQL_TIME *ltime, ulonglong fuzzydate) const;
longlong Item_val_int_signed_typecast(Item *item) const;
longlong Item_val_int_unsigned_typecast(Item *item) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
......@@ -2063,6 +2075,8 @@ class Type_handler_year: public Type_handler_int_result
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool Item_get_date(Item *item, MYSQL_TIME *ltime, ulonglong fuzzydate) const;
};
......
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