diff options
-rw-r--r-- | sql/item.cc | 119 | ||||
-rw-r--r-- | sql/item.h | 81 | ||||
-rw-r--r-- | sql/item_func.h | 130 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 36 | ||||
-rw-r--r-- | sql/item_timefunc.h | 243 | ||||
-rw-r--r-- | sql/sql_type.cc | 51 | ||||
-rw-r--r-- | sql/sql_type.h | 169 | ||||
-rw-r--r-- | storage/connect/ha_connect.cc | 2 |
8 files changed, 494 insertions, 337 deletions
diff --git a/sql/item.cc b/sql/item.cc index f0020543aec..6be086d507c 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -264,18 +264,6 @@ String *Item::val_string_from_decimal(String *str) } -/* - All val_xxx_from_date() must call this method, to expose consistent behaviour - regarding SQL_MODE when converting DATE/DATETIME to other data types. -*/ -bool Item::get_temporal_with_sql_mode(MYSQL_TIME *ltime) -{ - return get_date(ltime, field_type() == MYSQL_TYPE_TIME - ? TIME_TIME_ONLY - : sql_mode_for_dates(current_thd)); -} - - longlong Item::val_int_from_str(int *error) { char buff[MAX_FIELD_WIDTH]; @@ -326,21 +314,6 @@ longlong Item::val_int_unsigned_typecast_from_int() } -String *Item::val_string_from_date(String *str) -{ - MYSQL_TIME ltime; - if (get_temporal_with_sql_mode(<ime) || - str->alloc(MAX_DATE_STRING_REP_LENGTH)) - { - null_value= 1; - return (String *) 0; - } - str->length(my_TIME_to_str(<ime, const_cast<char*>(str->ptr()), decimals)); - str->set_charset(&my_charset_numeric); - return str; -} - - my_decimal *Item::val_decimal_from_real(my_decimal *decimal_value) { double nr= val_real(); @@ -372,54 +345,6 @@ my_decimal *Item::val_decimal_from_string(my_decimal *decimal_value) } -my_decimal *Item::val_decimal_from_date(my_decimal *decimal_value) -{ - DBUG_ASSERT(is_fixed()); - MYSQL_TIME ltime; - if (get_temporal_with_sql_mode(<ime)) - { - my_decimal_set_zero(decimal_value); - null_value= 1; // set NULL, stop processing - return 0; - } - return date2my_decimal(<ime, decimal_value); -} - - -my_decimal *Item::val_decimal_from_time(my_decimal *decimal_value) -{ - DBUG_ASSERT(is_fixed()); - MYSQL_TIME ltime; - if (get_time(<ime)) - { - my_decimal_set_zero(decimal_value); - return 0; - } - return date2my_decimal(<ime, decimal_value); -} - - -longlong Item::val_int_from_date() -{ - DBUG_ASSERT(is_fixed()); - MYSQL_TIME ltime; - if (get_temporal_with_sql_mode(<ime)) - return 0; - longlong v= TIME_to_ulonglong(<ime); - return ltime.neg ? -v : v; -} - - -double Item::val_real_from_date() -{ - DBUG_ASSERT(is_fixed()); - MYSQL_TIME ltime; - if (get_temporal_with_sql_mode(<ime)) - return 0; - return TIME_to_double(<ime); -} - - double Item::val_real_from_decimal() { /* Note that fix_fields may not be called for Item_avg_field items */ @@ -10097,50 +10022,6 @@ longlong Item_cache_temporal::val_time_packed() } -String *Item_cache_temporal::val_str(String *str) -{ - if (!has_value()) - { - null_value= true; - return NULL; - } - return val_string_from_date(str); -} - - -my_decimal *Item_cache_temporal::val_decimal(my_decimal *decimal_value) -{ - if ((!value_cached && !cache_value()) || null_value) - { - null_value= true; - return NULL; - } - return val_decimal_from_date(decimal_value); -} - - -longlong Item_cache_temporal::val_int() -{ - if ((!value_cached && !cache_value()) || null_value) - { - null_value= true; - return 0; - } - return val_int_from_date(); -} - - -double Item_cache_temporal::val_real() -{ - if ((!value_cached && !cache_value()) || null_value) - { - null_value= true; - return 0; - } - return val_real_from_date(); -} - - bool Item_cache_temporal::cache_value() { if (!example) diff --git a/sql/item.h b/sql/item.h index cf9e8cd922c..8fbb3a2403e 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1379,14 +1379,10 @@ public: String *val_string_from_real(String *str); String *val_string_from_int(String *str); String *val_string_from_decimal(String *str); - String *val_string_from_date(String *str); my_decimal *val_decimal_from_real(my_decimal *decimal_value); my_decimal *val_decimal_from_int(my_decimal *decimal_value); my_decimal *val_decimal_from_string(my_decimal *decimal_value); - my_decimal *val_decimal_from_date(my_decimal *decimal_value); - my_decimal *val_decimal_from_time(my_decimal *decimal_value); longlong val_int_from_decimal(); - longlong val_int_from_date(); longlong val_int_from_real() { DBUG_ASSERT(is_fixed()); @@ -1394,10 +1390,6 @@ public: } longlong val_int_from_str(int *error); double val_real_from_decimal(); - double val_real_from_date(); - - // Get TIME, DATE or DATETIME using proper sql_mode flags for the field type - bool get_temporal_with_sql_mode(MYSQL_TIME *ltime); int save_time_in_field(Field *field, bool no_conversions); int save_date_in_field(Field *field, bool no_conversions); @@ -4623,15 +4615,6 @@ public: } const MYSQL_TIME *const_ptr_mysql_time() const { return &cached_time; } - bool get_date_with_sql_mode(MYSQL_TIME *to); - String *val_str(String *str) - { return val_string_from_date(str); } - longlong val_int() - { return val_int_from_date(); } - double val_real() - { return val_real_from_date(); } - my_decimal *val_decimal(my_decimal *decimal_value) - { return val_decimal_from_date(decimal_value); } int save_in_field(Field *field, bool no_conversions) { return save_date_in_field(field, no_conversions); } }; @@ -4659,6 +4642,10 @@ public: const Type_handler *type_handler() const { return &type_handler_newdate; } void print(String *str, enum_query_type query_type); Item *clone_item(THD *thd); + longlong val_int() { return Date(this).to_longlong(); } + double val_real() { return Date(this).to_double(); } + String *val_str(String *to) { return Date(this).to_string(to); } + my_decimal *val_decimal(my_decimal *to) { return Date(this).to_decimal(to); } bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); Item *get_copy(THD *thd) { return get_item_copy<Item_date_literal>(thd, this); } @@ -4679,6 +4666,10 @@ public: const Type_handler *type_handler() const { return &type_handler_time2; } void print(String *str, enum_query_type query_type); Item *clone_item(THD *thd); + longlong val_int() { return Time(this).to_longlong(); } + double val_real() { return Time(this).to_double(); } + String *val_str(String *to) { return Time(this).to_string(to, decimals); } + my_decimal *val_decimal(my_decimal *to) { return Time(this).to_decimal(to); } bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); Item *get_copy(THD *thd) { return get_item_copy<Item_time_literal>(thd, this); } @@ -4701,6 +4692,16 @@ public: const Type_handler *type_handler() const { return &type_handler_datetime2; } void print(String *str, enum_query_type query_type); Item *clone_item(THD *thd); + longlong val_int() { return Datetime(this).to_longlong(); } + double val_real() { return Datetime(this).to_double(); } + String *val_str(String *to) + { + return Datetime(this).to_string(to, decimals); + } + my_decimal *val_decimal(my_decimal *to) + { + return Datetime(this).to_decimal(to); + } bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date); Item *get_copy(THD *thd) { return get_item_copy<Item_datetime_literal>(thd, this); } @@ -6490,12 +6491,8 @@ class Item_cache_temporal: public Item_cache_int protected: Item_cache_temporal(THD *thd, const Type_handler *handler); public: - String* val_str(String *str); - my_decimal *val_decimal(my_decimal *); - longlong val_int(); longlong val_datetime_packed(); longlong val_time_packed(); - double val_real(); bool cache_value(); bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); int save_in_field(Field *field, bool no_conversions); @@ -6520,6 +6517,22 @@ public: Item *get_copy(THD *thd) { return get_item_copy<Item_cache_time>(thd, this); } Item *make_literal(THD *); + longlong val_int() + { + return has_value() ? Time(this).to_longlong() : 0; + } + double val_real() + { + return has_value() ? Time(this).to_double() : 0; + } + String *val_str(String *to) + { + return has_value() ? Time(this).to_string(to, decimals) : NULL; + } + my_decimal *val_decimal(my_decimal *to) + { + return has_value() ? Time(this).to_decimal(to) : NULL; + } }; @@ -6531,6 +6544,22 @@ public: Item *get_copy(THD *thd) { return get_item_copy<Item_cache_datetime>(thd, this); } Item *make_literal(THD *); + longlong val_int() + { + return has_value() ? Datetime(this).to_longlong() : 0; + } + double val_real() + { + return has_value() ? Datetime(this).to_double() : 0; + } + String *val_str(String *to) + { + return has_value() ? Datetime(this).to_string(to, decimals) : NULL; + } + my_decimal *val_decimal(my_decimal *to) + { + return has_value() ? Datetime(this).to_decimal(to) : NULL; + } }; @@ -6542,6 +6571,16 @@ public: Item *get_copy(THD *thd) { return get_item_copy<Item_cache_date>(thd, this); } Item *make_literal(THD *); + longlong val_int() { return has_value() ? Date(this).to_longlong() : 0; } + double val_real() { return has_value() ? Date(this).to_double() : 0; } + String *val_str(String *to) + { + return has_value() ? Date(this).to_string(to) : NULL; + } + my_decimal *val_decimal(my_decimal *to) + { + return has_value() ? Date(this).to_decimal(to) : NULL; + } }; diff --git a/sql/item_func.h b/sql/item_func.h index 131d038668d..947d1c8cc9d 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -55,6 +55,7 @@ protected: bool check_argument_types_can_return_text(uint start, uint end) const; bool check_argument_types_can_return_date(uint start, uint end) const; bool check_argument_types_can_return_time(uint start, uint end) const; + void print_cast_temporal(String *str, enum_query_type query_type); public: table_map not_null_tables_cache; @@ -466,6 +467,135 @@ public: virtual const Type_handler *return_type_handler() const= 0; virtual bool fix_length_and_dec(Item_handled_func *) const= 0; }; + + /** + Abstract class for functions returning TIME, DATE, DATETIME or string values, + whose data type depends on parameters and is set at fix_fields time. + */ + class Handler_temporal: public Handler + { + public: + String *val_str(Item_handled_func *item, String *to) const + { + StringBuffer<MAX_FIELD_WIDTH> ascii_buf; + return item->val_str_from_val_str_ascii(to, &ascii_buf); + } + }; + + /** + Abstract class for functions returning strings, + which are generated from get_date() results, + when get_date() can return different MYSQL_TIMESTAMP_XXX per row. + */ + class Handler_temporal_string: public Handler_temporal + { + public: + const Type_handler *return_type_handler() const + { + return &type_handler_string; + } + double val_real(Item_handled_func *item) const + { + return Temporal_hybrid(item).to_double(); + } + longlong val_int(Item_handled_func *item) const + { + return Temporal_hybrid(item).to_longlong(); + } + my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const + { + return Temporal_hybrid(item).to_decimal(to); + } + String *val_str_ascii(Item_handled_func *item, String *to) const + { + return Temporal_hybrid(item).to_string(to, item->decimals); + } + }; + + + class Handler_date: public Handler_temporal + { + public: + const Type_handler *return_type_handler() const + { + return &type_handler_newdate; + } + bool fix_length_and_dec(Item_handled_func *item) const + { + item->fix_attributes_date(); + return false; + } + double val_real(Item_handled_func *item) const + { + return Date(item).to_double(); + } + longlong val_int(Item_handled_func *item) const + { + return Date(item).to_longlong(); + } + my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const + { + return Date(item).to_decimal(to); + } + String *val_str_ascii(Item_handled_func *item, String *to) const + { + return Date(item).to_string(to); + } + }; + + + class Handler_time: public Handler_temporal + { + public: + const Type_handler *return_type_handler() const + { + return &type_handler_time2; + } + double val_real(Item_handled_func *item) const + { + return Time(item).to_double(); + } + longlong val_int(Item_handled_func *item) const + { + return Time(item).to_longlong(); + } + my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const + { + return Time(item).to_decimal(to); + } + String *val_str_ascii(Item_handled_func *item, String *to) const + { + return Time(item).to_string(to, item->decimals); + } + }; + + + class Handler_datetime: public Handler_temporal + { + public: + const Type_handler *return_type_handler() const + { + return &type_handler_datetime2; + } + double val_real(Item_handled_func *item) const + { + return Datetime(item).to_double(); + } + longlong val_int(Item_handled_func *item) const + { + return Datetime(item).to_longlong(); + } + my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const + { + return Datetime(item).to_decimal(to); + } + String *val_str_ascii(Item_handled_func *item, String *to) const + { + return Datetime(item).to_string(to, item->decimals); + } + }; + + protected: const Handler *m_func_handler; public: diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index d167fdb0ea5..3ac0342e89a 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1498,31 +1498,6 @@ bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval) } -String *Item_temporal_func::val_str(String *str) -{ - DBUG_ASSERT(fixed == 1); - return val_string_from_date(str); -} - - -String *Func_handler_temporal_hybrid::val_str_ascii(Item_handled_func *item, - String *str) const -{ - DBUG_ASSERT(item->is_fixed()); - MYSQL_TIME ltime; - - if (get_date(item, <ime, 0) || - (item->null_value= my_TIME_to_str(<ime, str, item->decimals))) - return (String *) 0; - - /* Check that the returned timestamp type matches to the function type */ - DBUG_ASSERT(item->field_type() == MYSQL_TYPE_STRING || - ltime.time_type == MYSQL_TIMESTAMP_NONE || - ltime.time_type == return_type_handler()->mysql_timestamp_type()); - return str; -} - - bool Item_func_from_days::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) { longlong value=args[0]->val_int(); @@ -1668,7 +1643,7 @@ bool Item_func_now::fix_fields(THD *thd, Item **items) func_name(), TIME_SECOND_PART_DIGITS); return 1; } - return Item_temporal_func::fix_fields(thd, items); + return Item_datetimefunc::fix_fields(thd, items); } void Item_func_now::print(String *str, enum_query_type query_type) @@ -1695,7 +1670,7 @@ int Item_func_now_local::save_in_field(Field *field, bool no_conversions) return 0; } else - return Item_temporal_func::save_in_field(field, no_conversions); + return Item_datetimefunc::save_in_field(field, no_conversions); } @@ -2081,7 +2056,7 @@ bool Item_func_convert_tz::get_date(MYSQL_TIME *ltime, void Item_func_convert_tz::cleanup() { from_tz_cached= to_tz_cached= 0; - Item_temporal_func::cleanup(); + Item_datetimefunc::cleanup(); } @@ -2327,13 +2302,14 @@ bool Item_char_typecast::eq(const Item *item, bool binary_cmp) const return 1; } -void Item_temporal_typecast::print(String *str, enum_query_type query_type) +void Item_func::print_cast_temporal(String *str, enum_query_type query_type) { char buf[32]; str->append(STRING_WITH_LEN("cast(")); args[0]->print(str, query_type); str->append(STRING_WITH_LEN(" as ")); - str->append(cast_type()); + const Name name= type_handler()->name(); + str->append(name.ptr(), name.length()); if (decimals && decimals != NOT_FIXED_DEC) { str->append('('); diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 45d23c13474..f9709b8f72a 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -581,29 +581,17 @@ public: }; -class Item_temporal_func: public Item_func +class Item_datefunc :public Item_func { public: - Item_temporal_func(THD *thd): Item_func(thd) {} - Item_temporal_func(THD *thd, Item *a): Item_func(thd, a) {} - Item_temporal_func(THD *thd, Item *a, Item *b): Item_func(thd, a, b) {} - Item_temporal_func(THD *thd, Item *a, Item *b, Item *c): Item_func(thd, a, b, c) {} - String *val_str(String *str); - longlong val_int() { return val_int_from_date(); } - double val_real() { return val_real_from_date(); } - bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date) { DBUG_ASSERT(0); return 1; } - my_decimal *val_decimal(my_decimal *decimal_value) - { return val_decimal_from_date(decimal_value); } -}; - - -class Item_datefunc :public Item_temporal_func -{ -public: - Item_datefunc(THD *thd): Item_temporal_func(thd) { } - Item_datefunc(THD *thd, Item *a): Item_temporal_func(thd, a) { } - Item_datefunc(THD *thd, Item *a, Item *b): Item_temporal_func(thd, a, b) { } + Item_datefunc(THD *thd): Item_func(thd) { } + Item_datefunc(THD *thd, Item *a): Item_func(thd, a) { } + Item_datefunc(THD *thd, Item *a, Item *b): Item_func(thd, a, b) { } const Type_handler *type_handler() const { return &type_handler_newdate; } + longlong val_int() { return Date(this).to_longlong(); } + double val_real() { return Date(this).to_double(); } + String *val_str(String *to) { return Date(this).to_string(to); } + my_decimal *val_decimal(my_decimal *to) { return Date(this).to_decimal(to); } bool fix_length_and_dec() { fix_attributes_date(); @@ -613,28 +601,34 @@ public: }; -class Item_timefunc :public Item_temporal_func +class Item_timefunc :public Item_func { public: - Item_timefunc(THD *thd): Item_temporal_func(thd) {} - Item_timefunc(THD *thd, Item *a): Item_temporal_func(thd, a) {} - Item_timefunc(THD *thd, Item *a, Item *b): Item_temporal_func(thd, a, b) {} - Item_timefunc(THD *thd, Item *a, Item *b, Item *c): - Item_temporal_func(thd, a, b ,c) {} + Item_timefunc(THD *thd): Item_func(thd) {} + Item_timefunc(THD *thd, Item *a): Item_func(thd, a) {} + Item_timefunc(THD *thd, Item *a, Item *b): Item_func(thd, a, b) {} + Item_timefunc(THD *thd, Item *a, Item *b, Item *c): Item_func(thd, a, b ,c) {} const Type_handler *type_handler() const { return &type_handler_time2; } + longlong val_int() { return Time(this).to_longlong(); } + double val_real() { return Time(this).to_double(); } + String *val_str(String *to) { return Time(this).to_string(to, decimals); } + my_decimal *val_decimal(my_decimal *to) { return Time(this).to_decimal(to); } }; -class Item_datetimefunc :public Item_temporal_func +class Item_datetimefunc :public Item_func { public: - Item_datetimefunc(THD *thd): Item_temporal_func(thd) {} - Item_datetimefunc(THD *thd, Item *a): Item_temporal_func(thd, a) {} - Item_datetimefunc(THD *thd, Item *a, Item *b): - Item_temporal_func(thd, a, b) {} + Item_datetimefunc(THD *thd): Item_func(thd) {} + Item_datetimefunc(THD *thd, Item *a): Item_func(thd, a) {} + Item_datetimefunc(THD *thd, Item *a, Item *b): Item_func(thd, a, b) {} Item_datetimefunc(THD *thd, Item *a, Item *b, Item *c): - Item_temporal_func(thd, a, b ,c) {} + Item_func(thd, a, b ,c) {} const Type_handler *type_handler() const { return &type_handler_datetime2; } + longlong val_int() { return Datetime(this).to_longlong(); } + double val_real() { return Datetime(this).to_double(); } + String *val_str(String *to) { return Datetime(this).to_string(to, decimals); } + my_decimal *val_decimal(my_decimal *to) { return Datetime(this).to_decimal(to); } }; @@ -1116,22 +1110,16 @@ public: }; -class Item_temporal_typecast: public Item_temporal_func -{ -public: - Item_temporal_typecast(THD *thd, Item *a): Item_temporal_func(thd, a) {} - virtual const char *cast_type() const = 0; - void print(String *str, enum_query_type query_type); -}; - -class Item_date_typecast :public Item_temporal_typecast +class Item_date_typecast :public Item_datefunc { public: - Item_date_typecast(THD *thd, Item *a): Item_temporal_typecast(thd, a) {} + Item_date_typecast(THD *thd, Item *a): Item_datefunc(thd, a) {} const char *func_name() const { return "cast_as_date"; } + void print(String *str, enum_query_type query_type) + { + print_cast_temporal(str, query_type); + } bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date); - const char *cast_type() const { return "date"; } - const Type_handler *type_handler() const { return &type_handler_newdate; } bool fix_length_and_dec() { return args[0]->type_handler()->Item_date_typecast_fix_length_and_dec(this); @@ -1141,15 +1129,17 @@ public: }; -class Item_time_typecast :public Item_temporal_typecast +class Item_time_typecast :public Item_timefunc { public: Item_time_typecast(THD *thd, Item *a, uint dec_arg): - Item_temporal_typecast(thd, a) { decimals= dec_arg; } + Item_timefunc(thd, a) { decimals= dec_arg; } const char *func_name() const { return "cast_as_time"; } + void print(String *str, enum_query_type query_type) + { + print_cast_temporal(str, query_type); + } bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date); - const char *cast_type() const { return "time"; } - const Type_handler *type_handler() const { return &type_handler_time2; } bool fix_length_and_dec() { return args[0]->type_handler()-> @@ -1160,14 +1150,16 @@ public: }; -class Item_datetime_typecast :public Item_temporal_typecast +class Item_datetime_typecast :public Item_datetimefunc { public: Item_datetime_typecast(THD *thd, Item *a, uint dec_arg): - Item_temporal_typecast(thd, a) { decimals= dec_arg; } + Item_datetimefunc(thd, a) { decimals= dec_arg; } const char *func_name() const { return "cast_as_datetime"; } - const char *cast_type() const { return "datetime"; } - const Type_handler *type_handler() const { return &type_handler_datetime2; } + void print(String *str, enum_query_type query_type) + { + print_cast_temporal(str, query_type); + } bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date); bool fix_length_and_dec() { @@ -1400,35 +1392,7 @@ public: /*****************************************************************************/ -/** - Abstract class for functions returning TIME, DATE, DATETIME or string values, - whose data type depends on parameters and is set at fix_fields time. -*/ -class Func_handler_temporal_hybrid: public Item_handled_func::Handler -{ -public: - double val_real(Item_handled_func *item) const - { - return item->val_real_from_date(); - } - longlong val_int(Item_handled_func *item) const - { - return item->val_int_from_date(); - } - my_decimal *val_decimal(Item_handled_func *item, my_decimal *to) const - { - return item->val_decimal_from_date(to); - } - String *val_str(Item_handled_func *item, String *to) const - { - StringBuffer<MAX_FIELD_WIDTH> ascii_buf; - return item->val_str_from_val_str_ascii(to, &ascii_buf); - } - String *val_str_ascii(Item_handled_func *, String *to) const; -}; - - -class Func_handler_date_add_interval: public Func_handler_temporal_hybrid +class Func_handler_date_add_interval { protected: static uint interval_dec(const Item *item, interval_type int_type) @@ -1462,13 +1426,10 @@ protected: class Func_handler_date_add_interval_datetime: - public Func_handler_date_add_interval + public Item_handled_func::Handler_datetime, + public Func_handler_date_add_interval { public: - const Type_handler *return_type_handler() const - { - return &type_handler_datetime2; - } bool fix_length_and_dec(Item_handled_func *item) const { uint dec= MY_MAX(item->arguments()[0]->datetime_precision(), @@ -1490,25 +1451,18 @@ public: class Func_handler_date_add_interval_datetime_arg0_time: - public Func_handler_date_add_interval_datetime + public Func_handler_date_add_interval_datetime { public: bool get_date(Item_handled_func *item, MYSQL_TIME *to, ulonglong fuzzy) const; }; -class Func_handler_date_add_interval_date: public Func_handler_date_add_interval +class Func_handler_date_add_interval_date: + public Item_handled_func::Handler_date, + public Func_handler_date_add_interval { public: - const Type_handler *return_type_handler() const - { - return &type_handler_newdate; - } - bool fix_length_and_dec(Item_handled_func *item) const - { - item->fix_attributes_date(); - return false; - } bool get_date(Item_handled_func *item, MYSQL_TIME *to, ulonglong fuzzy) const { Date d(current_thd, item->arguments()[0], 0); @@ -1522,13 +1476,11 @@ public: }; -class Func_handler_date_add_interval_time: public Func_handler_date_add_interval +class Func_handler_date_add_interval_time: + public Item_handled_func::Handler_time, + public Func_handler_date_add_interval { public: - const Type_handler *return_type_handler() const - { - return &type_handler_time2; - } bool fix_length_and_dec(Item_handled_func *item) const { uint dec= MY_MAX(item->arguments()[0]->time_precision(), @@ -1549,13 +1501,10 @@ public: class Func_handler_date_add_interval_string: - public Func_handler_date_add_interval + public Item_handled_func::Handler_temporal_string, + public Func_handler_date_add_interval { public: - const Type_handler *return_type_handler() const - { - return &type_handler_string; - } bool fix_length_and_dec(Item_handled_func *item) const { uint dec= MY_MAX(item->arguments()[0]->datetime_precision(), @@ -1578,25 +1527,22 @@ public: }; - -class Func_handler_add_time: public Func_handler_temporal_hybrid +class Func_handler_sign { protected: int m_sign; - Func_handler_add_time(int sign) :m_sign(sign) { } + Func_handler_sign(int sign) :m_sign(sign) { } }; -class Func_handler_add_time_datetime: public Func_handler_add_time +class Func_handler_add_time_datetime: + public Item_handled_func::Handler_datetime, + public Func_handler_sign { public: Func_handler_add_time_datetime(int sign) - :Func_handler_add_time(sign) + :Func_handler_sign(sign) { } - const Type_handler *return_type_handler() const - { - return &type_handler_datetime2; - } bool fix_length_and_dec(Item_handled_func *item) const { uint dec= MY_MAX(item->arguments()[0]->datetime_precision(), @@ -1617,16 +1563,14 @@ public: }; -class Func_handler_add_time_time: public Func_handler_add_time +class Func_handler_add_time_time: + public Item_handled_func::Handler_time, + public Func_handler_sign { public: Func_handler_add_time_time(int sign) - :Func_handler_add_time(sign) + :Func_handler_sign(sign) { } - const Type_handler *return_type_handler() const - { - return &type_handler_time2; - } bool fix_length_and_dec(Item_handled_func *item) const { uint dec= MY_MAX(item->arguments()[0]->time_precision(), @@ -1647,16 +1591,14 @@ public: }; -class Func_handler_add_time_string: public Func_handler_add_time +class Func_handler_add_time_string: + public Item_handled_func::Handler_temporal_string, + public Func_handler_sign { public: Func_handler_add_time_string(int sign) - :Func_handler_add_time(sign) + :Func_handler_sign(sign) { } - const Type_handler *return_type_handler() const - { - return &type_handler_string; - } bool fix_length_and_dec(Item_handled_func *item) const { uint dec= MY_MAX(item->arguments()[0]->decimals, @@ -1678,17 +1620,18 @@ public: return (item->null_value= (l_time1.time_type == MYSQL_TIMESTAMP_TIME ? add.to_time(to, item->decimals) : add.to_datetime(to))); - } }; -class Func_handler_str_to_date_datetime: public Func_handler_temporal_hybrid +class Func_handler_str_to_date_datetime_sec: + public Item_handled_func::Handler_datetime { public: - const Type_handler *return_type_handler() const + bool fix_length_and_dec(Item_handled_func *item) const { - return &type_handler_datetime2; + item->fix_attributes_datetime(0); + return false; } bool get_date(Item_handled_func *item, MYSQL_TIME *to, ulonglong fuzzy) const { @@ -1698,20 +1641,8 @@ public: }; -class Func_handler_str_to_date_datetime_sec: - public Func_handler_str_to_date_datetime -{ -public: - bool fix_length_and_dec(Item_handled_func *item) const - { - item->fix_attributes_datetime(0); - return false; - } -}; - - class Func_handler_str_to_date_datetime_usec: - public Func_handler_str_to_date_datetime + public Item_handled_func::Handler_datetime { public: bool fix_length_and_dec(Item_handled_func *item) const @@ -1719,36 +1650,28 @@ public: item->fix_attributes_datetime(TIME_SECOND_PART_DIGITS); return false; } + bool get_date(Item_handled_func *item, MYSQL_TIME *to, ulonglong fuzzy) const + { + return static_cast<Item_func_str_to_date*>(item)-> + get_date_common(to, fuzzy, MYSQL_TIMESTAMP_DATETIME); + } }; -class Func_handler_str_to_date_date: public Func_handler_temporal_hybrid +class Func_handler_str_to_date_date: public Item_handled_func::Handler_date { public: - const Type_handler *return_type_handler() const - { - return &type_handler_newdate; - } bool get_date(Item_handled_func *item, MYSQL_TIME *to, ulonglong fuzzy) const { return static_cast<Item_func_str_to_date*>(item)-> get_date_common(to, fuzzy, MYSQL_TIMESTAMP_DATE); } - bool fix_length_and_dec(Item_handled_func *item) const - { - item->fix_attributes_date(); - return false; - } }; -class Func_handler_str_to_date_time: public Func_handler_temporal_hybrid +class Func_handler_str_to_date_time: public Item_handled_func::Handler_time { public: - const Type_handler *return_type_handler() const - { - return &type_handler_time2; - } bool get_date(Item_handled_func *item, MYSQL_TIME *to, ulonglong fuzzy) const { if (static_cast<Item_func_str_to_date*>(item)-> diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 436778fb32f..0a9f4544919 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -130,6 +130,26 @@ bool Type_handler_data::init() Type_handler_data *type_handler_data= NULL; +my_decimal *Temporal::to_decimal(my_decimal *to) const +{ + return date2my_decimal(this, to); +} + + +my_decimal *Temporal::bad_to_decimal(my_decimal *to) const +{ + my_decimal_set_zero(to); + return NULL; +} + + +Temporal_hybrid::Temporal_hybrid(THD *thd, Item *item) +{ + if (item->get_date(this, sql_mode_for_dates(thd))) + time_type= MYSQL_TIMESTAMP_NONE; +} + + void Time::make_from_item(Item *item, const Options opt) { if (item->get_date(this, opt.get_date_flags())) @@ -165,6 +185,12 @@ void Temporal_with_date::make_from_item(THD *thd, Item *item, sql_mode_t flags) } +void Temporal_with_date::make_from_item(THD *thd, Item *item) +{ + return make_from_item(thd, item, sql_mode_for_dates(thd)); +} + + uint Type_std_attributes::count_max_decimals(Item **item, uint nitems) { uint res= 0; @@ -4118,10 +4144,31 @@ String *Type_handler_string_result:: } -String *Type_handler_temporal_result:: +String *Type_handler_time_common:: + Item_func_min_max_val_str(Item_func_min_max *func, String *str) const +{ + return Time(func).to_string(str, func->decimals); +} + + +String *Type_handler_date_common:: + Item_func_min_max_val_str(Item_func_min_max *func, String *str) const +{ + return Date(func).to_string(str); +} + + +String *Type_handler_datetime_common:: + Item_func_min_max_val_str(Item_func_min_max *func, String *str) const +{ + return Datetime(func).to_string(str, func->decimals); +} + + +String *Type_handler_timestamp_common:: Item_func_min_max_val_str(Item_func_min_max *func, String *str) const { - return func->val_string_from_date(str); + return Datetime(func).to_string(str, func->decimals); } diff --git a/sql/sql_type.h b/sql/sql_type.h index e50df06f084..8df308c58e6 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -77,6 +77,7 @@ struct TABLE; struct SORT_FIELD_ATTR; class Vers_history_point; +#define my_charset_numeric my_charset_latin1 enum scalar_comparison_op { @@ -148,6 +149,62 @@ public: }; +class Temporal: protected MYSQL_TIME +{ +protected: + bool is_valid_temporal() const + { + DBUG_ASSERT(time_type != MYSQL_TIMESTAMP_ERROR); + return time_type != MYSQL_TIMESTAMP_NONE; + } + my_decimal *bad_to_decimal(my_decimal *to) const; + my_decimal *to_decimal(my_decimal *to) const; + static double to_double(bool negate, ulonglong num, ulong frac) + { + double d= (double) num + frac / (double) TIME_SECOND_PART_FACTOR; + return negate ? -d : d; + } +public: +}; + + +/* + Use this class when you need to get a MYSQL_TIME from an Item + using Item's native timestamp type, without automatic timestamp + type conversion. +*/ +class Temporal_hybrid: private Temporal +{ +public: + Temporal_hybrid(THD *thd, Item *item); + Temporal_hybrid(Item *item) { *this= Temporal_hybrid(current_thd, item); } + longlong to_longlong() const + { + if (!is_valid_temporal()) + return 0; + ulonglong v= TIME_to_ulonglong(this); + return neg ? -(longlong) v : (longlong) v; + } + double to_double() const + { + return is_valid_temporal() ? TIME_to_double(this) : 0; + } + my_decimal *to_decimal(my_decimal *to) + { + return is_valid_temporal() ? Temporal::to_decimal(to) : bad_to_decimal(to); + } + String *to_string(String *str, uint dec) const + { + if (!is_valid_temporal()) + return NULL; + str->set_charset(&my_charset_numeric); + if (!str->alloc(MAX_DATE_STRING_REP_LENGTH)) + str->length(my_TIME_to_str(this, const_cast<char*>(str->ptr()), dec)); + return str; + } +}; + + /** Class Time is designed to store valid TIME values. @@ -166,7 +223,7 @@ public: Time derives from MYSQL_TIME privately to make sure it is accessed externally only in the valid state. */ -class Time: private MYSQL_TIME +class Time: private Temporal { public: enum datetime_to_time_mode_t @@ -333,6 +390,31 @@ public: { return neg ? -to_seconds_abs() : to_seconds_abs(); } + longlong to_longlong() const + { + if (!is_valid_time()) + return 0; + ulonglong v= TIME_to_ulonglong_time(this); + return neg ? -(longlong) v : (longlong) v; + } + double to_double() const + { + return !is_valid_time() ? 0 : + Temporal::to_double(neg, TIME_to_ulonglong_time(this), second_part); + } + String *to_string(String *str, uint dec) const + { + if (!is_valid_time()) + return NULL; + str->set_charset(&my_charset_numeric); + if (!str->alloc(MAX_DATE_STRING_REP_LENGTH)) + str->length(my_time_to_str(this, const_cast<char*>(str->ptr()), dec)); + return str; + } + my_decimal *to_decimal(my_decimal *to) + { + return is_valid_time() ? Temporal::to_decimal(to) : bad_to_decimal(to); + } }; @@ -359,14 +441,19 @@ public: it is accessed externally only in the valid state. */ -class Temporal_with_date: protected MYSQL_TIME +class Temporal_with_date: protected Temporal { protected: void make_from_item(THD *thd, Item *item, sql_mode_t flags); + void make_from_item(THD *thd, Item *item); Temporal_with_date(THD *thd, Item *item, sql_mode_t flags) { make_from_item(thd, item, flags); } + Temporal_with_date(THD *thd, Item *item) + { + make_from_item(thd, item); + } public: bool check_date_with_warn(ulonglong flags) { @@ -403,6 +490,20 @@ public: datetime_to_date(this); DBUG_ASSERT(is_valid_value_slow()); } + Date(THD *thd, Item *item) + :Temporal_with_date(thd, item) + { + if (time_type == MYSQL_TIMESTAMP_DATETIME) + datetime_to_date(this); + DBUG_ASSERT(is_valid_value_slow()); + } + Date(Item *item) + :Temporal_with_date(current_thd, item) + { + if (time_type == MYSQL_TIMESTAMP_DATETIME) + datetime_to_date(this); + DBUG_ASSERT(is_valid_value_slow()); + } Date(const Temporal_with_date *d) :Temporal_with_date(*d) { @@ -430,6 +531,27 @@ public: *ltime= *this; return false; } + longlong to_longlong() const + { + return is_valid_date() ? (longlong) TIME_to_ulonglong_date(this) : 0LL; + } + double to_double() const + { + return (double) to_longlong(); + } + String *to_string(String *str) const + { + if (!is_valid_date()) + return NULL; + str->set_charset(&my_charset_numeric); + if (!str->alloc(MAX_DATE_STRING_REP_LENGTH)) + str->length(my_date_to_str(this, const_cast<char*>(str->ptr()))); + return str; + } + my_decimal *to_decimal(my_decimal *to) + { + return is_valid_date() ? Temporal::to_decimal(to) : bad_to_decimal(to); + } }; @@ -462,6 +584,20 @@ public: date_to_datetime(this); DBUG_ASSERT(is_valid_value_slow()); } + Datetime(THD *thd, Item *item) + :Temporal_with_date(thd, item) + { + if (time_type == MYSQL_TIMESTAMP_DATE) + date_to_datetime(this); + DBUG_ASSERT(is_valid_value_slow()); + } + Datetime(Item *item) + :Temporal_with_date(current_thd, item) + { + if (time_type == MYSQL_TIMESTAMP_DATE) + date_to_datetime(this); + DBUG_ASSERT(is_valid_value_slow()); + } bool is_valid_datetime() const { /* @@ -507,6 +643,29 @@ public: ltime->time_type= type; return false; } + longlong to_longlong() const + { + return is_valid_datetime() ? + (longlong) TIME_to_ulonglong_datetime(this) : 0LL; + } + double to_double() const + { + return !is_valid_datetime() ? 0 : + Temporal::to_double(neg, TIME_to_ulonglong_datetime(this), second_part); + } + String *to_string(String *str, uint dec) const + { + if (!is_valid_datetime()) + return NULL; + str->set_charset(&my_charset_numeric); + if (!str->alloc(MAX_DATE_STRING_REP_LENGTH)) + str->length(my_datetime_to_str(this, const_cast<char*>(str->ptr()), dec)); + return str; + } + my_decimal *to_decimal(my_decimal *to) + { + return is_valid_datetime() ? Temporal::to_decimal(to) : bad_to_decimal(to); + } }; /* @@ -534,7 +693,6 @@ public: #define MY_COLL_CMP_CONV (MY_COLL_ALLOW_CONV | MY_COLL_DISALLOW_NONE) -#define my_charset_numeric my_charset_latin1 #define MY_REPERTOIRE_NUMERIC MY_REPERTOIRE_ASCII @@ -2448,7 +2606,6 @@ public: bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *, MYSQL_TIME *, ulonglong fuzzydate) const; - String *Item_func_min_max_val_str(Item_func_min_max *, String *) const; double Item_func_min_max_val_real(Item_func_min_max *) const; longlong Item_func_min_max_val_int(Item_func_min_max *) const; my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, @@ -3071,6 +3228,7 @@ public: bool Item_func_hybrid_field_type_get_date(Item_func_hybrid_field_type *, MYSQL_TIME *, ulonglong fuzzydate) const; + String *Item_func_min_max_val_str(Item_func_min_max *, String *) const; bool Item_func_min_max_get_date(Item_func_min_max*, MYSQL_TIME *, ulonglong fuzzydate) const; longlong Item_func_between_val_int(Item_func_between *func) const; @@ -3183,6 +3341,7 @@ public: uint Item_decimal_precision(const Item *item) const; String *print_item_value(THD *thd, Item *item, String *str) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const; + String *Item_func_min_max_val_str(Item_func_min_max *, String *) const; bool Item_hybrid_func_fix_attributes(THD *thd, const char *name, Type_handler_hybrid_field_type *, @@ -3274,6 +3433,7 @@ public: } String *print_item_value(THD *thd, Item *item, String *str) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const; + String *Item_func_min_max_val_str(Item_func_min_max *, String *) const; bool Item_hybrid_func_fix_attributes(THD *thd, const char *name, Type_handler_hybrid_field_type *, @@ -3373,6 +3533,7 @@ public: } String *print_item_value(THD *thd, Item *item, String *str) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const; + String *Item_func_min_max_val_str(Item_func_min_max *, String *) const; bool Item_hybrid_func_fix_attributes(THD *thd, const char *name, Type_handler_hybrid_field_type *, diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 4abc4ad1d17..d7e3aebbe21 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -2742,7 +2742,7 @@ PFIL ha_connect::CondFilter(PGLOBAL g, Item *cond) case TIME_RESULT: pp->Type= TYPE_DATE; pp->Value= PlugSubAlloc(g, NULL, sizeof(int)); - *((int*)pp->Value)= (int)pval->val_int_from_date(); + *((int*)pp->Value)= (int) Temporal_hybrid(pval).to_longlong(); break; case REAL_RESULT: pp->Type= TYPE_DOUBLE; |