diff options
Diffstat (limited to 'sql/item_timefunc.h')
-rw-r--r-- | sql/item_timefunc.h | 464 |
1 files changed, 372 insertions, 92 deletions
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index e04e24627d9..d84267a5066 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -27,7 +27,10 @@ public: Item_func_period_add(Item *a,Item *b) :Item_int_func(a,b) {} longlong val_int(); const char *func_name() const { return "period_add"; } - void fix_length_and_dec() { max_length=6; } + void fix_length_and_dec() + { + max_length=6*default_charset()->mbmaxlen; + } }; @@ -37,7 +40,11 @@ public: Item_func_period_diff(Item *a,Item *b) :Item_int_func(a,b) {} longlong val_int(); const char *func_name() const { return "period_diff"; } - void fix_length_and_dec() { decimals=0; max_length=6; } + void fix_length_and_dec() + { + decimals=0; + max_length=6*default_charset()->mbmaxlen; + } }; @@ -47,7 +54,12 @@ public: Item_func_to_days(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "to_days"; } - void fix_length_and_dec() { decimals=0; max_length=6; maybe_null=1; } + void fix_length_and_dec() + { + decimals=0; + max_length=6*default_charset()->mbmaxlen; + maybe_null=1; + } }; @@ -57,7 +69,12 @@ public: Item_func_dayofmonth(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "dayofmonth"; } - void fix_length_and_dec() { decimals=0; max_length=2; maybe_null=1; } + void fix_length_and_dec() + { + decimals=0; + max_length=2*default_charset()->mbmaxlen; + maybe_null=1; + } }; @@ -67,10 +84,20 @@ public: Item_func_month(Item *a) :Item_func(a) {} longlong val_int(); double val() { return (double) Item_func_month::val_int(); } - String *val_str(String *str) { str->set(val_int()); return null_value ? 0 : str;} + String *val_str(String *str) + { + str->set(val_int(), default_charset()); + return null_value ? 0 : str; + } const char *func_name() const { return "month"; } enum Item_result result_type () const { return INT_RESULT; } - void fix_length_and_dec() { decimals=0; max_length=2; maybe_null=1; } + void fix_length_and_dec() + { + collation.set(default_charset()); + decimals=0; + max_length=2*default_charset()->mbmaxlen; + maybe_null=1; + } }; @@ -81,7 +108,13 @@ public: const char *func_name() const { return "monthname"; } String *val_str(String *str); enum Item_result result_type () const { return STRING_RESULT; } - void fix_length_and_dec() { decimals=0; max_length=10; maybe_null=1; } + void fix_length_and_dec() + { + collation.set(default_charset()); + decimals=0; + max_length=10*default_charset()->mbmaxlen; + maybe_null=1; + } }; @@ -91,7 +124,12 @@ public: Item_func_dayofyear(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "dayofyear"; } - void fix_length_and_dec() { decimals=0; max_length=3; maybe_null=1; } + void fix_length_and_dec() + { + decimals=0; + max_length=3*default_charset()->mbmaxlen; + maybe_null=1; + } }; @@ -101,7 +139,12 @@ public: Item_func_hour(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "hour"; } - void fix_length_and_dec() { decimals=0; max_length=2; maybe_null=1; } + void fix_length_and_dec() + { + decimals=0; + max_length=2*default_charset()->mbmaxlen; + maybe_null=1; + } }; @@ -111,7 +154,12 @@ public: Item_func_minute(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "minute"; } - void fix_length_and_dec() { decimals=0; max_length=2; maybe_null=1; } + void fix_length_and_dec() + { + decimals=0; + max_length=2*default_charset()->mbmaxlen; + maybe_null=1; + } }; @@ -121,7 +169,12 @@ public: Item_func_quarter(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "quarter"; } - void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1; } + void fix_length_and_dec() + { + decimals=0; + max_length=1*default_charset()->mbmaxlen; + maybe_null=1; + } }; @@ -131,7 +184,12 @@ public: Item_func_second(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "second"; } - void fix_length_and_dec() { decimals=0; max_length=2; maybe_null=1; } + void fix_length_and_dec() + { + decimals=0; + max_length=2*default_charset()->mbmaxlen; + maybe_null=1; + } }; @@ -141,7 +199,12 @@ public: Item_func_week(Item *a,Item *b) :Item_int_func(a,b) {} longlong val_int(); const char *func_name() const { return "week"; } - void fix_length_and_dec() { decimals=0; max_length=2; maybe_null=1; } + void fix_length_and_dec() + { + decimals=0; + max_length=2*default_charset()->mbmaxlen; + maybe_null=1; + } }; class Item_func_yearweek :public Item_int_func @@ -150,7 +213,12 @@ public: Item_func_yearweek(Item *a,Item *b) :Item_int_func(a,b) {} longlong val_int(); const char *func_name() const { return "yearweek"; } - void fix_length_and_dec() { decimals=0; max_length=6; maybe_null=1; } + void fix_length_and_dec() + { + decimals=0; + max_length=6*default_charset()->mbmaxlen; + maybe_null=1; + } }; @@ -160,7 +228,12 @@ public: Item_func_year(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "year"; } - void fix_length_and_dec() { decimals=0; max_length=4; maybe_null=1; } + void fix_length_and_dec() + { + decimals=0; + max_length=4*default_charset()->mbmaxlen; + maybe_null=1; + } }; @@ -172,11 +245,20 @@ public: :Item_func(a), odbc_type(type_arg) {} longlong val_int(); double val() { return (double) val_int(); } - String *val_str(String *str) { str->set(val_int()); return null_value ? 0 : str;} + String *val_str(String *str) + { + str->set(val_int(), default_charset()); + return null_value ? 0 : str; + } const char *func_name() const { return "weekday"; } enum Item_result result_type () const { return INT_RESULT; } - void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1; } - unsigned int size_of() { return sizeof(*this);} + void fix_length_and_dec() + { + collation.set(default_charset()); + decimals=0; + max_length=1*default_charset()->mbmaxlen; + maybe_null=1; + } }; class Item_func_dayname :public Item_func_weekday @@ -186,7 +268,13 @@ class Item_func_dayname :public Item_func_weekday const char *func_name() const { return "dayname"; } String *val_str(String *str); enum Item_result result_type () const { return STRING_RESULT; } - void fix_length_and_dec() { decimals=0; max_length=9; maybe_null=1; } + void fix_length_and_dec() + { + collation.set(default_charset()); + decimals=0; + max_length=9*default_charset()->mbmaxlen; + maybe_null=1; + } }; @@ -200,9 +288,9 @@ public: const char *func_name() const { return "timestamp"; } void fix_length_and_dec() { - decimals=0; max_length=10; + decimals=0; + max_length=10*default_charset()->mbmaxlen; } - unsigned int size_of() { return sizeof(*this);} }; @@ -214,7 +302,8 @@ public: const char *func_name() const { return "time_to_sec"; } void fix_length_and_dec() { - decimals=0; max_length=10; + decimals=0; + max_length=10*default_charset()->mbmaxlen; } }; @@ -227,20 +316,22 @@ public: Item_date() :Item_func() {} Item_date(Item *a) :Item_func(a) {} enum Item_result result_type () const { return STRING_RESULT; } + enum_field_types field_type() const { return MYSQL_TYPE_DATE; } String *val_str(String *str); double val() { return (double) val_int(); } const char *func_name() const { return "date"; } - void fix_length_and_dec() { decimals=0; max_length=10; } - bool save_in_field(Field *to, bool no_conversions); - void make_field(Send_field *tmp_field) - { - init_make_field(tmp_field,FIELD_TYPE_DATE); + void fix_length_and_dec() + { + collation.set(default_charset()); + decimals=0; + max_length=10*default_charset()->mbmaxlen; } + int save_in_field(Field *to, bool no_conversions); + Field *tmp_table_field() { return result_field; } Field *tmp_table_field(TABLE *t_arg) { - return (!t_arg) ? result_field : new Field_date(maybe_null, name, t_arg); + return (new Field_date(maybe_null, name, t_arg, default_charset())); } - unsigned int size_of() { return sizeof(*this);} }; @@ -250,64 +341,105 @@ public: Item_date_func() :Item_str_func() {} Item_date_func(Item *a) :Item_str_func(a) {} Item_date_func(Item *a,Item *b) :Item_str_func(a,b) {} - void make_field(Send_field *tmp_field) - { - init_make_field(tmp_field,FIELD_TYPE_DATETIME); - } + enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } + Field *tmp_table_field() { return result_field; } Field *tmp_table_field(TABLE *t_arg) { - return (!t_arg) ? result_field : new Field_datetime(maybe_null, name, - t_arg); + return (new Field_datetime(maybe_null, name, t_arg, default_charset())); } - unsigned int size_of() { return sizeof(*this);} }; +/* Abstract CURTIME function. Children should define what timezone is used */ + class Item_func_curtime :public Item_func { longlong value; - char buff[9]; + char buff[9*2+32]; uint buff_length; public: Item_func_curtime() :Item_func() {} Item_func_curtime(Item *a) :Item_func(a) {} enum Item_result result_type () const { return STRING_RESULT; } + enum_field_types field_type() const { return MYSQL_TYPE_TIME; } double val() { return (double) value; } longlong val_int() { return value; } - String *val_str(String *str) - { str_value.set(buff,buff_length); return &str_value; } - const char *func_name() const { return "curtime"; } + String *val_str(String *str); void fix_length_and_dec(); - void make_field(Send_field *tmp_field) - { - init_make_field(tmp_field,FIELD_TYPE_TIME); - } + Field *tmp_table_field() { return result_field; } Field *tmp_table_field(TABLE *t_arg) { - return (!t_arg) ? result_field : new Field_time(maybe_null, name, t_arg); - } - unsigned int size_of() { return sizeof(*this);} + return (new Field_time(maybe_null, name, t_arg, default_charset())); + } + /* + Abstract method that defines which time zone is used for conversion. + Converts time from time_t representation to broken down representation + in struct tm using gmtime_r or localtime_r functions. + */ + virtual void store_now_in_tm(time_t now, struct tm *now_tm)=0; +}; + + +class Item_func_curtime_local :public Item_func_curtime +{ +public: + Item_func_curtime_local() :Item_func_curtime() {} + Item_func_curtime_local(Item *a) :Item_func_curtime(a) {} + const char *func_name() const { return "curtime"; } + void store_now_in_tm(time_t now, struct tm *now_tm); +}; + + +class Item_func_curtime_utc :public Item_func_curtime +{ +public: + Item_func_curtime_utc() :Item_func_curtime() {} + Item_func_curtime_utc(Item *a) :Item_func_curtime(a) {} + const char *func_name() const { return "utc_time"; } + void store_now_in_tm(time_t now, struct tm *now_tm); }; +/* Abstract CURDATE function. See also Item_func_curtime. */ + class Item_func_curdate :public Item_date { longlong value; TIME ltime; public: Item_func_curdate() :Item_date() {} + void set_result_from_tm(struct tm *now); longlong val_int() { return (value) ; } - const char *func_name() const { return "curdate"; } - void fix_length_and_dec(); /* Retrieves curtime */ + void fix_length_and_dec(); bool get_date(TIME *res,bool fuzzy_date); - unsigned int size_of() { return sizeof(*this);} + virtual void store_now_in_tm(time_t now, struct tm *now_tm)=0; }; +class Item_func_curdate_local :public Item_func_curdate +{ +public: + Item_func_curdate_local() :Item_func_curdate() {} + const char *func_name() const { return "curdate"; } + void store_now_in_tm(time_t now, struct tm *now_tm); +}; + + +class Item_func_curdate_utc :public Item_func_curdate +{ +public: + Item_func_curdate_utc() :Item_func_curdate() {} + const char *func_name() const { return "utc_date"; } + void store_now_in_tm(time_t now, struct tm *now_tm); +}; + + +/* Abstract CURRENT_TIMESTAMP function. See also Item_func_curtime */ + class Item_func_now :public Item_date_func { longlong value; - char buff[20]; + char buff[20*2+32]; // +32 to make my_snprintf_{8bit|ucs2} happy uint buff_length; TIME ltime; public: @@ -316,13 +448,31 @@ public: enum Item_result result_type () const { return STRING_RESULT; } double val() { return (double) value; } longlong val_int() { return value; } - bool save_in_field(Field *to, bool no_conversions); - String *val_str(String *str) - { str_value.set(buff,buff_length); return &str_value; } - const char *func_name() const { return "now"; } + int save_in_field(Field *to, bool no_conversions); + String *val_str(String *str); void fix_length_and_dec(); bool get_date(TIME *res,bool fuzzy_date); - unsigned int size_of() { return sizeof(*this);} + virtual void store_now_in_tm(time_t now, struct tm *now_tm)=0; +}; + + +class Item_func_now_local :public Item_func_now +{ +public: + Item_func_now_local() :Item_func_now() {} + Item_func_now_local(Item *a) :Item_func_now(a) {} + const char *func_name() const { return "now"; } + void store_now_in_tm(time_t now, struct tm *now_tm); +}; + + +class Item_func_now_utc :public Item_func_now +{ +public: + Item_func_now_utc() :Item_func_now() {} + Item_func_now_utc(Item *a) :Item_func_now(a) {} + const char *func_name() const { return "utc_timestamp"; } + void store_now_in_tm(time_t now, struct tm *now_tm); }; @@ -347,7 +497,6 @@ public: const char *func_name() const { return "date_format"; } void fix_length_and_dec(); uint format_length(const String *format); - unsigned int size_of() { return sizeof(*this);} }; @@ -359,8 +508,12 @@ class Item_func_from_unixtime :public Item_date_func longlong val_int(); String *val_str(String *str); const char *func_name() const { return "from_unixtime"; } - void fix_length_and_dec() { decimals=0; max_length=19; } -// enum Item_result result_type () const { return STRING_RESULT; } + void fix_length_and_dec() + { + collation.set(default_charset()); + decimals=0; + max_length=19*default_charset()->mbmaxlen; + } bool get_date(TIME *res,bool fuzzy_date); }; @@ -372,42 +525,53 @@ public: double val() { return (double) Item_func_sec_to_time::val_int(); } longlong val_int(); String *val_str(String *); - void fix_length_and_dec() { maybe_null=1; max_length=13; } - const char *func_name() const { return "sec_to_time"; } - void make_field(Send_field *tmp_field) - { - init_make_field(tmp_field,FIELD_TYPE_TIME); + void fix_length_and_dec() + { + collation.set(default_charset()); + maybe_null=1; + max_length=13*default_charset()->mbmaxlen; } + enum_field_types field_type() const { return MYSQL_TYPE_TIME; } + const char *func_name() const { return "sec_to_time"; } + Field *tmp_table_field() { return result_field; } Field *tmp_table_field(TABLE *t_arg) { - return (!t_arg) ? result_field : new Field_time(maybe_null, name, t_arg); + return (new Field_time(maybe_null, name, t_arg, default_charset())); } }; +/* + The following must be sorted so that simple intervals comes first. + (get_interval_value() depends on this) +*/ + +enum interval_type +{ + INTERVAL_YEAR, INTERVAL_MONTH, INTERVAL_DAY, INTERVAL_HOUR, INTERVAL_MINUTE, + INTERVAL_SECOND, INTERVAL_MICROSECOND ,INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, + INTERVAL_DAY_MINUTE, INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE, + INTERVAL_HOUR_SECOND, INTERVAL_MINUTE_SECOND, INTERVAL_DAY_MICROSECOND, + INTERVAL_HOUR_MICROSECOND, INTERVAL_MINUTE_MICROSECOND, INTERVAL_SECOND_MICROSECOND +}; -enum interval_type { INTERVAL_YEAR, INTERVAL_MONTH, INTERVAL_DAY, - INTERVAL_HOUR, INTERVAL_MINUTE, INTERVAL_SECOND, - INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, - INTERVAL_DAY_MINUTE, INTERVAL_DAY_SECOND, - INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND, - INTERVAL_MINUTE_SECOND}; class Item_date_add_interval :public Item_date_func { const interval_type int_type; String value; const bool date_sub_interval; + enum_field_types cached_field_type; public: Item_date_add_interval(Item *a,Item *b,interval_type type_arg,bool neg_arg) :Item_date_func(a,b),int_type(type_arg), date_sub_interval(neg_arg) {} String *val_str(String *); const char *func_name() const { return "date_add_interval"; } - void fix_length_and_dec() { maybe_null=1; max_length=19; value.alloc(32);} + void fix_length_and_dec(); + enum_field_types field_type() const { return cached_field_type; } double val() { return (double) val_int(); } longlong val_int(); bool get_date(TIME *res,bool fuzzy_date); - unsigned int size_of() { return sizeof(*this);} }; @@ -423,7 +587,6 @@ class Item_extract :public Item_int_func const char *func_name() const { return "extract"; } void fix_length_and_dec(); bool eq(const Item *item, bool binary_cmp) const; - unsigned int size_of() { return sizeof(*this);} }; @@ -433,17 +596,33 @@ public: Item_typecast(Item *a) :Item_str_func(a) {} const char *func_name() const { return "char"; } String *val_str(String *a) - { a=args[0]->val_str(a); null_value=args[0]->null_value; return a; } - void fix_length_and_dec() { max_length=args[0]->max_length; } + { + String *tmp=args[0]->val_str(a); + null_value=args[0]->null_value; + if (tmp) + tmp->set_charset(collation.collation); + return tmp; + } + void fix_length_and_dec() + { + collation.set(default_charset()); + max_length=args[0]->max_length; + } void print(String *str); }; class Item_char_typecast :public Item_typecast { + int cast_length; + CHARSET_INFO *cast_cs; + bool charset_conversion; + String tmp_value; public: - Item_char_typecast(Item *a) :Item_typecast(a) {} - void fix_length_and_dec() { binary=0; max_length=args[0]->max_length; } + Item_char_typecast(Item *a, int length_arg, CHARSET_INFO *cs_arg) + :Item_typecast(a), cast_length(length_arg), cast_cs(cs_arg) {} + String *val_str(String *a); + void fix_length_and_dec(); }; @@ -451,14 +630,14 @@ class Item_date_typecast :public Item_typecast { public: Item_date_typecast(Item *a) :Item_typecast(a) {} + String *val_str(String *str); + bool get_date(TIME *ltime, bool fuzzy_date); const char *func_name() const { return "date"; } - void make_field(Send_field *tmp_field) - { - init_make_field(tmp_field,FIELD_TYPE_DATE); - } + enum_field_types field_type() const { return MYSQL_TYPE_DATE; } + Field *tmp_table_field() { return result_field; } Field *tmp_table_field(TABLE *t_arg) { - return (!t_arg) ? result_field : new Field_date(maybe_null, name, t_arg); + return (new Field_date(maybe_null, name, t_arg, default_charset())); } }; @@ -467,14 +646,14 @@ class Item_time_typecast :public Item_typecast { public: Item_time_typecast(Item *a) :Item_typecast(a) {} + String *val_str(String *str); + bool get_time(TIME *ltime); const char *func_name() const { return "time"; } - void make_field(Send_field *tmp_field) - { - init_make_field(tmp_field,FIELD_TYPE_TIME); - } + enum_field_types field_type() const { return MYSQL_TYPE_TIME; } + Field *tmp_table_field() { return result_field; } Field *tmp_table_field(TABLE *t_arg) { - return (!t_arg) ? result_field : new Field_time(maybe_null, name, t_arg); + return (new Field_time(maybe_null, name, t_arg, default_charset())); } }; @@ -483,14 +662,115 @@ class Item_datetime_typecast :public Item_typecast { public: Item_datetime_typecast(Item *a) :Item_typecast(a) {} + String *val_str(String *str); const char *func_name() const { return "datetime"; } - void make_field(Send_field *tmp_field) + enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } + Field *tmp_table_field() { return result_field; } + Field *tmp_table_field(TABLE *t_arg) { - init_make_field(tmp_field,FIELD_TYPE_DATETIME); + return (new Field_datetime(maybe_null, name, t_arg, default_charset())); } +}; + +class Item_func_makedate :public Item_str_func +{ +public: + Item_func_makedate(Item *a,Item *b) :Item_str_func(a,b) {} + String *val_str(String *str); + const char *func_name() const { return "makedate"; } + enum_field_types field_type() const { return MYSQL_TYPE_DATE; } + void fix_length_and_dec() + { + decimals=0; + max_length=8*MY_CHARSET_BIN_MB_MAXLEN; + } + Field *tmp_table_field() { return result_field; } Field *tmp_table_field(TABLE *t_arg) { - return (!t_arg) ? result_field : new Field_datetime(maybe_null, name, - t_arg); + return (new Field_date(maybe_null, name, t_arg, &my_charset_bin)); + } +}; + + +class Item_func_add_time :public Item_str_func +{ + const bool is_date; + int sign; + enum_field_types cached_field_type; + +public: + Item_func_add_time(Item *a, Item *b, bool type_arg, bool neg_arg) + :Item_str_func(a, b), is_date(type_arg) { sign= neg_arg ? -1 : 1; } + String *val_str(String *str); + const char *func_name() const { return "addtime"; } + enum_field_types field_type() const { return cached_field_type; } + void fix_length_and_dec(); + +/* + TODO: + Change this when we support + microseconds in TIME/DATETIME +*/ + Field *tmp_table_field() { return result_field; } + Field *tmp_table_field(TABLE *t_arg) + { + if (cached_field_type == MYSQL_TYPE_TIME) + return (new Field_time(maybe_null, name, t_arg, &my_charset_bin)); + else if (cached_field_type == MYSQL_TYPE_DATETIME) + return (new Field_datetime(maybe_null, name, t_arg, &my_charset_bin)); + return (new Field_string(max_length, maybe_null, name, t_arg, &my_charset_bin)); + } +}; + +class Item_func_timediff :public Item_str_func +{ +public: + Item_func_timediff(Item *a, Item *b) + :Item_str_func(a, b) {} + String *val_str(String *str); + const char *func_name() const { return "timediff"; } + enum_field_types field_type() const { return MYSQL_TYPE_TIME; } + void fix_length_and_dec() + { + decimals=0; + max_length=17*MY_CHARSET_BIN_MB_MAXLEN; + } + Field *tmp_table_field() { return result_field; } + Field *tmp_table_field(TABLE *t_arg) + { + return (new Field_time(maybe_null, name, t_arg, &my_charset_bin)); + } +}; + +class Item_func_maketime :public Item_str_func +{ +public: + Item_func_maketime(Item *a, Item *b, Item *c) + :Item_str_func(a, b ,c) {} + String *val_str(String *str); + const char *func_name() const { return "maketime"; } + enum_field_types field_type() const { return MYSQL_TYPE_TIME; } + void fix_length_and_dec() + { + decimals=0; + max_length=8*MY_CHARSET_BIN_MB_MAXLEN; + } + Field *tmp_table_field() { return result_field; } + Field *tmp_table_field(TABLE *t_arg) + { + return (new Field_time(maybe_null, name, t_arg, &my_charset_bin)); + } +}; + +class Item_func_microsecond :public Item_int_func +{ +public: + Item_func_microsecond(Item *a) :Item_int_func(a) {} + longlong val_int(); + const char *func_name() const { return "microsecond"; } + void fix_length_and_dec() + { + decimals=0; + maybe_null=1; } }; |