summaryrefslogtreecommitdiffstats
path: root/sql/item_timefunc.h
diff options
context:
space:
mode:
Diffstat (limited to 'sql/item_timefunc.h')
-rw-r--r--sql/item_timefunc.h1776
1 files changed, 1776 insertions, 0 deletions
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
new file mode 100644
index 00000000..a910b2cb
--- /dev/null
+++ b/sql/item_timefunc.h
@@ -0,0 +1,1776 @@
+#ifndef ITEM_TIMEFUNC_INCLUDED
+#define ITEM_TIMEFUNC_INCLUDED
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates.
+ Copyright (c) 2009-2011, Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
+
+
+/* Function items used by mysql */
+
+#ifdef USE_PRAGMA_INTERFACE
+#pragma interface /* gcc class implementation */
+#endif
+
+class MY_LOCALE;
+
+
+bool get_interval_value(THD *thd, Item *args,
+ interval_type int_type, INTERVAL *interval);
+
+
+class Item_long_func_date_field: public Item_long_func
+{
+ bool check_arguments() const
+ { return args[0]->check_type_can_return_date(func_name()); }
+public:
+ Item_long_func_date_field(THD *thd, Item *a)
+ :Item_long_func(thd, a) { }
+};
+
+
+class Item_long_func_time_field: public Item_long_func
+{
+ bool check_arguments() const
+ { return args[0]->check_type_can_return_time(func_name()); }
+public:
+ Item_long_func_time_field(THD *thd, Item *a)
+ :Item_long_func(thd, a) { }
+};
+
+
+class Item_func_period_add :public Item_long_func
+{
+ bool check_arguments() const
+ { return check_argument_types_can_return_int(0, 2); }
+public:
+ Item_func_period_add(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {}
+ longlong val_int();
+ const char *func_name() const { return "period_add"; }
+ bool fix_length_and_dec()
+ {
+ max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
+ return FALSE;
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_period_add>(thd, this); }
+};
+
+
+class Item_func_period_diff :public Item_long_func
+{
+ bool check_arguments() const
+ { return check_argument_types_can_return_int(0, 2); }
+public:
+ Item_func_period_diff(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {}
+ longlong val_int();
+ const char *func_name() const { return "period_diff"; }
+ bool fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
+ return FALSE;
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_period_diff>(thd, this); }
+};
+
+
+class Item_func_to_days :public Item_long_func_date_field
+{
+public:
+ Item_func_to_days(THD *thd, Item *a): Item_long_func_date_field(thd, a) {}
+ longlong val_int();
+ const char *func_name() const { return "to_days"; }
+ bool fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
+ maybe_null=1;
+ return FALSE;
+ }
+ enum_monotonicity_info get_monotonicity_info() const;
+ longlong val_int_endpoint(bool left_endp, bool *incl_endp);
+ bool check_partition_func_processor(void *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(void *arg) { return FALSE;}
+ bool check_valid_arguments_processor(void *int_arg)
+ {
+ return !has_date_args();
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_to_days>(thd, this); }
+};
+
+
+class Item_func_to_seconds :public Item_longlong_func
+{
+ bool check_arguments() const
+ { return check_argument_types_can_return_date(0, arg_count); }
+public:
+ Item_func_to_seconds(THD *thd, Item *a): Item_longlong_func(thd, a) {}
+ longlong val_int();
+ const char *func_name() const { return "to_seconds"; }
+ bool fix_length_and_dec()
+ {
+ decimals=0;
+ fix_char_length(12);
+ maybe_null= 1;
+ return FALSE;
+ }
+ enum_monotonicity_info get_monotonicity_info() const;
+ longlong val_int_endpoint(bool left_endp, bool *incl_endp);
+ bool check_partition_func_processor(void *bool_arg) { return FALSE;}
+
+ /* Only meaningful with date part and optional time part */
+ bool check_valid_arguments_processor(void *int_arg)
+ {
+ return !has_date_args();
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_to_seconds>(thd, this); }
+};
+
+
+class Item_func_dayofmonth :public Item_long_func_date_field
+{
+public:
+ Item_func_dayofmonth(THD *thd, Item *a): Item_long_func_date_field(thd, a) {}
+ longlong val_int();
+ const char *func_name() const { return "dayofmonth"; }
+ bool fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=2*MY_CHARSET_BIN_MB_MAXLEN;
+ maybe_null=1;
+ return FALSE;
+ }
+ bool check_partition_func_processor(void *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(void *arg) { return FALSE;}
+ bool check_valid_arguments_processor(void *int_arg)
+ {
+ return !has_date_args();
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_dayofmonth>(thd, this); }
+};
+
+
+class Item_func_month :public Item_long_func
+{
+public:
+ Item_func_month(THD *thd, Item *a): Item_long_func(thd, a)
+ { }
+ longlong val_int();
+ const char *func_name() const { return "month"; }
+ bool fix_length_and_dec()
+ {
+ decimals= 0;
+ fix_char_length(2);
+ maybe_null=1;
+ return FALSE;
+ }
+ bool check_partition_func_processor(void *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(void *arg) { return FALSE;}
+ bool check_valid_arguments_processor(void *int_arg)
+ {
+ return !has_date_args();
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_month>(thd, this); }
+};
+
+
+class Item_func_monthname :public Item_str_func
+{
+ MY_LOCALE *locale;
+public:
+ Item_func_monthname(THD *thd, Item *a): Item_str_func(thd, a) {}
+ const char *func_name() const { return "monthname"; }
+ String *val_str(String *str);
+ bool fix_length_and_dec();
+ bool check_partition_func_processor(void *int_arg) {return TRUE;}
+ bool check_valid_arguments_processor(void *int_arg)
+ {
+ return !has_date_args();
+ }
+ bool check_vcol_func_processor(void *arg)
+ {
+ return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC);
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_monthname>(thd, this); }
+};
+
+
+class Item_func_dayofyear :public Item_long_func_date_field
+{
+public:
+ Item_func_dayofyear(THD *thd, Item *a): Item_long_func_date_field(thd, a) {}
+ longlong val_int();
+ const char *func_name() const { return "dayofyear"; }
+ bool fix_length_and_dec()
+ {
+ decimals= 0;
+ fix_char_length(3);
+ maybe_null=1;
+ return FALSE;
+ }
+ bool check_partition_func_processor(void *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(void *arg) { return FALSE;}
+ bool check_valid_arguments_processor(void *int_arg)
+ {
+ return !has_date_args();
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_dayofyear>(thd, this); }
+};
+
+
+class Item_func_hour :public Item_long_func_time_field
+{
+public:
+ Item_func_hour(THD *thd, Item *a): Item_long_func_time_field(thd, a) {}
+ longlong val_int();
+ const char *func_name() const { return "hour"; }
+ bool fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=2*MY_CHARSET_BIN_MB_MAXLEN;
+ maybe_null=1;
+ return FALSE;
+ }
+ bool check_partition_func_processor(void *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(void *arg) { return FALSE;}
+ bool check_valid_arguments_processor(void *int_arg)
+ {
+ return !has_time_args();
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_hour>(thd, this); }
+};
+
+
+class Item_func_minute :public Item_long_func_time_field
+{
+public:
+ Item_func_minute(THD *thd, Item *a): Item_long_func_time_field(thd, a) {}
+ longlong val_int();
+ const char *func_name() const { return "minute"; }
+ bool fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=2*MY_CHARSET_BIN_MB_MAXLEN;
+ maybe_null=1;
+ return FALSE;
+ }
+ bool check_partition_func_processor(void *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(void *arg) { return FALSE;}
+ bool check_valid_arguments_processor(void *int_arg)
+ {
+ return !has_time_args();
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_minute>(thd, this); }
+};
+
+
+class Item_func_quarter :public Item_long_func_date_field
+{
+public:
+ Item_func_quarter(THD *thd, Item *a): Item_long_func_date_field(thd, a) {}
+ longlong val_int();
+ const char *func_name() const { return "quarter"; }
+ bool fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=1*MY_CHARSET_BIN_MB_MAXLEN;
+ maybe_null=1;
+ return FALSE;
+ }
+ bool check_partition_func_processor(void *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(void *arg) { return FALSE;}
+ bool check_valid_arguments_processor(void *int_arg)
+ {
+ return !has_date_args();
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_quarter>(thd, this); }
+};
+
+
+class Item_func_second :public Item_long_func_time_field
+{
+public:
+ Item_func_second(THD *thd, Item *a): Item_long_func_time_field(thd, a) {}
+ longlong val_int();
+ const char *func_name() const { return "second"; }
+ bool fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=2*MY_CHARSET_BIN_MB_MAXLEN;
+ maybe_null=1;
+ return FALSE;
+ }
+ bool check_partition_func_processor(void *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(void *arg) { return FALSE;}
+ bool check_valid_arguments_processor(void *int_arg)
+ {
+ return !has_time_args();
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_second>(thd, this); }
+};
+
+
+class Item_func_week :public Item_long_func
+{
+ bool check_arguments() const
+ {
+ return args[0]->check_type_can_return_date(func_name()) ||
+ (arg_count > 1 && args[1]->check_type_can_return_int(func_name()));
+ }
+public:
+ Item_func_week(THD *thd, Item *a): Item_long_func(thd, a) {}
+ Item_func_week(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {}
+ longlong val_int();
+ const char *func_name() const { return "week"; }
+ bool fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=2*MY_CHARSET_BIN_MB_MAXLEN;
+ maybe_null=1;
+ return FALSE;
+ }
+ bool check_vcol_func_processor(void *arg)
+ {
+ if (arg_count == 2)
+ return FALSE;
+ return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC);
+ }
+ bool check_valid_arguments_processor(void *int_arg)
+ {
+ return arg_count == 2;
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_week>(thd, this); }
+};
+
+class Item_func_yearweek :public Item_long_func
+{
+ bool check_arguments() const
+ {
+ return args[0]->check_type_can_return_date(func_name()) ||
+ args[1]->check_type_can_return_int(func_name());
+ }
+public:
+ Item_func_yearweek(THD *thd, Item *a, Item *b)
+ :Item_long_func(thd, a, b) {}
+ longlong val_int();
+ const char *func_name() const { return "yearweek"; }
+ bool fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
+ maybe_null=1;
+ return FALSE;
+ }
+ bool check_partition_func_processor(void *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(void *arg) { return FALSE;}
+ bool check_valid_arguments_processor(void *int_arg)
+ {
+ return !has_date_args();
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_yearweek>(thd, this); }
+};
+
+
+class Item_func_year :public Item_long_func_date_field
+{
+public:
+ Item_func_year(THD *thd, Item *a): Item_long_func_date_field(thd, a) {}
+ longlong val_int();
+ const char *func_name() const { return "year"; }
+ enum_monotonicity_info get_monotonicity_info() const;
+ longlong val_int_endpoint(bool left_endp, bool *incl_endp);
+ bool fix_length_and_dec()
+ {
+ decimals=0;
+ max_length=4*MY_CHARSET_BIN_MB_MAXLEN;
+ maybe_null=1;
+ return FALSE;
+ }
+ bool check_partition_func_processor(void *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(void *arg) { return FALSE;}
+ bool check_valid_arguments_processor(void *int_arg)
+ {
+ return !has_date_args();
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_year>(thd, this); }
+};
+
+
+class Item_func_weekday :public Item_long_func
+{
+ bool odbc_type;
+public:
+ Item_func_weekday(THD *thd, Item *a, bool type_arg):
+ Item_long_func(thd, a), odbc_type(type_arg) { }
+ longlong val_int();
+ const char *func_name() const
+ {
+ return (odbc_type ? "dayofweek" : "weekday");
+ }
+ bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
+ {
+ return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate);
+ }
+ bool fix_length_and_dec()
+ {
+ decimals= 0;
+ fix_char_length(1);
+ maybe_null=1;
+ return FALSE;
+ }
+ bool check_partition_func_processor(void *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(void *arg) { return FALSE;}
+ bool check_valid_arguments_processor(void *int_arg)
+ {
+ return !has_date_args();
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_weekday>(thd, this); }
+};
+
+class Item_func_dayname :public Item_str_func
+{
+ MY_LOCALE *locale;
+ public:
+ Item_func_dayname(THD *thd, Item *a): Item_str_func(thd, a) {}
+ const char *func_name() const { return "dayname"; }
+ String *val_str(String *str);
+ const Type_handler *type_handler() const { return &type_handler_varchar; }
+ bool fix_length_and_dec();
+ bool check_partition_func_processor(void *int_arg) {return TRUE;}
+ bool check_vcol_func_processor(void *arg)
+ {
+ return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC);
+ }
+ bool check_valid_arguments_processor(void *int_arg)
+ {
+ return !has_date_args();
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_dayname>(thd, this); }
+};
+
+
+class Item_func_seconds_hybrid: public Item_func_numhybrid
+{
+public:
+ Item_func_seconds_hybrid(THD *thd): Item_func_numhybrid(thd) {}
+ Item_func_seconds_hybrid(THD *thd, Item *a): Item_func_numhybrid(thd, a) {}
+ void fix_length_and_dec_generic(uint dec)
+ {
+ DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
+ decimals= dec;
+ max_length=17 + (decimals ? decimals + 1 : 0);
+ maybe_null= true;
+ if (decimals)
+ set_handler(&type_handler_newdecimal);
+ else
+ set_handler(type_handler_long_or_longlong());
+ }
+ double real_op() { DBUG_ASSERT(0); return 0; }
+ String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
+ bool date_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
+};
+
+
+class Item_func_unix_timestamp :public Item_func_seconds_hybrid
+{
+ bool get_timestamp_value(my_time_t *seconds, ulong *second_part);
+public:
+ Item_func_unix_timestamp(THD *thd): Item_func_seconds_hybrid(thd) {}
+ Item_func_unix_timestamp(THD *thd, Item *a):
+ Item_func_seconds_hybrid(thd, a) {}
+ const char *func_name() const { return "unix_timestamp"; }
+ enum_monotonicity_info get_monotonicity_info() const;
+ longlong val_int_endpoint(bool left_endp, bool *incl_endp);
+ bool check_partition_func_processor(void *int_arg) {return FALSE;}
+ /*
+ UNIX_TIMESTAMP() depends on the current timezone
+ (and thus may not be used as a partitioning function)
+ when its argument is NOT of the TIMESTAMP type.
+ */
+ bool check_valid_arguments_processor(void *int_arg)
+ {
+ return !has_timestamp_args();
+ }
+ bool check_vcol_func_processor(void *arg)
+ {
+ if (arg_count)
+ return FALSE;
+ return mark_unsupported_function(func_name(), "()", arg, VCOL_TIME_FUNC);
+ }
+ bool fix_length_and_dec()
+ {
+ fix_length_and_dec_generic(arg_count ?
+ args[0]->datetime_precision(current_thd) : 0);
+ return FALSE;
+ }
+ longlong int_op();
+ my_decimal *decimal_op(my_decimal* buf);
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_unix_timestamp>(thd, this); }
+};
+
+
+class Item_func_time_to_sec :public Item_func_seconds_hybrid
+{
+public:
+ Item_func_time_to_sec(THD *thd, Item *item):
+ Item_func_seconds_hybrid(thd, item) {}
+ const char *func_name() const { return "time_to_sec"; }
+ bool check_partition_func_processor(void *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(void *arg) { return FALSE;}
+ bool check_valid_arguments_processor(void *int_arg)
+ {
+ return !has_time_args();
+ }
+ bool fix_length_and_dec()
+ {
+ fix_length_and_dec_generic(args[0]->time_precision(current_thd));
+ return FALSE;
+ }
+ longlong int_op();
+ my_decimal *decimal_op(my_decimal* buf);
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_time_to_sec>(thd, this); }
+};
+
+
+class Item_datefunc :public Item_func
+{
+public:
+ 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();
+ maybe_null= (arg_count > 0);
+ return FALSE;
+ }
+};
+
+
+class Item_timefunc :public Item_func
+{
+public:
+ 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); }
+ bool val_native(THD *thd, Native *to)
+ {
+ return Time(thd, this).to_native(to, decimals);
+ }
+};
+
+
+class Item_datetimefunc :public Item_func
+{
+public:
+ 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_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); }
+};
+
+
+/* Abstract CURTIME function. Children should define what time zone is used */
+
+class Item_func_curtime :public Item_timefunc
+{
+ MYSQL_TIME ltime;
+ query_id_t last_query_id;
+public:
+ Item_func_curtime(THD *thd, uint dec): Item_timefunc(thd), last_query_id(0)
+ { decimals= dec; }
+ bool fix_fields(THD *, Item **);
+ bool fix_length_and_dec() { fix_attributes_time(decimals); return FALSE; }
+ bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate);
+ /*
+ Abstract method that defines which time zone is used for conversion.
+ Converts time current time in my_time_t representation to broken-down
+ MYSQL_TIME representation using UTC-SYSTEM or per-thread time zone.
+ */
+ virtual void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time)=0;
+ bool check_vcol_func_processor(void *arg)
+ {
+ return mark_unsupported_function(func_name(), "()", arg, VCOL_TIME_FUNC);
+ }
+ void print(String *str, enum_query_type query_type);
+};
+
+
+class Item_func_curtime_local :public Item_func_curtime
+{
+public:
+ Item_func_curtime_local(THD *thd, uint dec): Item_func_curtime(thd, dec) {}
+ const char *func_name() const { return "curtime"; }
+ virtual void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time);
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_curtime_local>(thd, this); }
+};
+
+
+class Item_func_curtime_utc :public Item_func_curtime
+{
+public:
+ Item_func_curtime_utc(THD *thd, uint dec): Item_func_curtime(thd, dec) {}
+ const char *func_name() const { return "utc_time"; }
+ virtual void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time);
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_curtime_utc>(thd, this); }
+};
+
+
+/* Abstract CURDATE function. See also Item_func_curtime. */
+
+class Item_func_curdate :public Item_datefunc
+{
+ query_id_t last_query_id;
+ MYSQL_TIME ltime;
+public:
+ Item_func_curdate(THD *thd): Item_datefunc(thd), last_query_id(0) {}
+ bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate);
+ virtual void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time)=0;
+ bool check_vcol_func_processor(void *arg)
+ {
+ return mark_unsupported_function(func_name(), "()", arg, VCOL_TIME_FUNC);
+ }
+};
+
+
+class Item_func_curdate_local :public Item_func_curdate
+{
+public:
+ Item_func_curdate_local(THD *thd): Item_func_curdate(thd) {}
+ const char *func_name() const { return "curdate"; }
+ void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time);
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_curdate_local>(thd, this); }
+};
+
+
+class Item_func_curdate_utc :public Item_func_curdate
+{
+public:
+ Item_func_curdate_utc(THD *thd): Item_func_curdate(thd) {}
+ const char *func_name() const { return "utc_date"; }
+ void store_now_in_TIME(THD* thd, MYSQL_TIME *now_time);
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_curdate_utc>(thd, this); }
+};
+
+
+/* Abstract CURRENT_TIMESTAMP function. See also Item_func_curtime */
+
+class Item_func_now :public Item_datetimefunc
+{
+ MYSQL_TIME ltime;
+ query_id_t last_query_id;
+public:
+ Item_func_now(THD *thd, uint dec): Item_datetimefunc(thd), last_query_id(0)
+ { decimals= dec; }
+ bool fix_fields(THD *, Item **);
+ bool fix_length_and_dec()
+ { fix_attributes_datetime(decimals); return FALSE;}
+ bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate);
+ virtual void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time)=0;
+ bool check_vcol_func_processor(void *arg)
+ {
+ /*
+ NOW is safe for replication as slaves will run with same time as
+ master
+ */
+ return mark_unsupported_function(func_name(), "()", arg, VCOL_TIME_FUNC);
+ }
+ void print(String *str, enum_query_type query_type);
+};
+
+
+class Item_func_now_local :public Item_func_now
+{
+public:
+ Item_func_now_local(THD *thd, uint dec): Item_func_now(thd, dec) {}
+ const char *func_name() const { return "current_timestamp"; }
+ int save_in_field(Field *field, bool no_conversions);
+ virtual void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time);
+ virtual enum Functype functype() const { return NOW_FUNC; }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_now_local>(thd, this); }
+};
+
+
+class Item_func_now_utc :public Item_func_now
+{
+public:
+ Item_func_now_utc(THD *thd, uint dec): Item_func_now(thd, dec) {}
+ const char *func_name() const { return "utc_timestamp"; }
+ virtual void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time);
+ virtual enum Functype functype() const { return NOW_UTC_FUNC; }
+ virtual bool check_vcol_func_processor(void *arg)
+ {
+ return mark_unsupported_function(func_name(), "()", arg,
+ VCOL_TIME_FUNC | VCOL_NON_DETERMINISTIC);
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_now_utc>(thd, this); }
+};
+
+
+/*
+ This is like NOW(), but always uses the real current time, not the
+ query_start(). This matches the Oracle behavior.
+*/
+class Item_func_sysdate_local :public Item_func_now
+{
+public:
+ Item_func_sysdate_local(THD *thd, uint dec): Item_func_now(thd, dec) {}
+ bool const_item() const { return 0; }
+ const char *func_name() const { return "sysdate"; }
+ void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time);
+ bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate);
+ table_map used_tables() const { return RAND_TABLE_BIT; }
+ bool check_vcol_func_processor(void *arg)
+ {
+ return mark_unsupported_function(func_name(), "()", arg,
+ VCOL_TIME_FUNC | VCOL_NON_DETERMINISTIC);
+ }
+ virtual enum Functype functype() const { return SYSDATE_FUNC; }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_sysdate_local>(thd, this); }
+};
+
+
+class Item_func_from_days :public Item_datefunc
+{
+ bool check_arguments() const
+ { return args[0]->check_type_can_return_int(func_name()); }
+public:
+ Item_func_from_days(THD *thd, Item *a): Item_datefunc(thd, a) {}
+ const char *func_name() const { return "from_days"; }
+ bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate);
+ bool check_partition_func_processor(void *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(void *arg) { return FALSE;}
+ bool check_valid_arguments_processor(void *int_arg)
+ {
+ return has_date_args() || has_time_args();
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_from_days>(thd, this); }
+};
+
+
+class Item_func_date_format :public Item_str_func
+{
+ bool check_arguments() const
+ {
+ return args[0]->check_type_can_return_date(func_name()) ||
+ check_argument_types_can_return_text(1, arg_count);
+ }
+ const MY_LOCALE *locale;
+ int fixed_length;
+ String value;
+protected:
+ bool is_time_format;
+public:
+ Item_func_date_format(THD *thd, Item *a, Item *b):
+ Item_str_func(thd, a, b), locale(0), is_time_format(false) {}
+ Item_func_date_format(THD *thd, Item *a, Item *b, Item *c):
+ Item_str_func(thd, a, b, c), locale(0), is_time_format(false) {}
+ String *val_str(String *str);
+ const char *func_name() const { return "date_format"; }
+ bool fix_length_and_dec();
+ uint format_length(const String *format);
+ bool eq(const Item *item, bool binary_cmp) const;
+ bool check_vcol_func_processor(void *arg)
+ {
+ if (arg_count > 2)
+ return false;
+ return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC);
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_date_format>(thd, this); }
+};
+
+class Item_func_time_format: public Item_func_date_format
+{
+public:
+ Item_func_time_format(THD *thd, Item *a, Item *b):
+ Item_func_date_format(thd, a, b) { is_time_format= true; }
+ const char *func_name() const { return "time_format"; }
+ bool check_vcol_func_processor(void *arg) { return false; }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_time_format>(thd, this); }
+};
+
+
+class Item_func_from_unixtime :public Item_datetimefunc
+{
+ bool check_arguments() const
+ { return args[0]->check_type_can_return_decimal(func_name()); }
+ Time_zone *tz;
+ public:
+ Item_func_from_unixtime(THD *thd, Item *a): Item_datetimefunc(thd, a) {}
+ const char *func_name() const { return "from_unixtime"; }
+ bool fix_length_and_dec();
+ bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate);
+ bool check_vcol_func_processor(void *arg)
+ {
+ return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC);
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_from_unixtime>(thd, this); }
+};
+
+
+/*
+ We need Time_zone class declaration for storing pointers in
+ Item_func_convert_tz.
+*/
+class Time_zone;
+
+/*
+ This class represents CONVERT_TZ() function.
+ The important fact about this function that it is handled in special way.
+ When such function is met in expression time_zone system tables are added
+ to global list of tables to open, so later those already opened and locked
+ tables can be used during this function calculation for loading time zone
+ descriptions.
+*/
+class Item_func_convert_tz :public Item_datetimefunc
+{
+ bool check_arguments() const
+ {
+ return args[0]->check_type_can_return_date(func_name()) ||
+ check_argument_types_can_return_text(1, arg_count);
+ }
+ /*
+ If time zone parameters are constants we are caching objects that
+ represent them (we use separate from_tz_cached/to_tz_cached members
+ to indicate this fact, since NULL is legal value for from_tz/to_tz
+ members.
+ */
+ bool from_tz_cached, to_tz_cached;
+ Time_zone *from_tz, *to_tz;
+ public:
+ Item_func_convert_tz(THD *thd, Item *a, Item *b, Item *c):
+ Item_datetimefunc(thd, a, b, c), from_tz_cached(0), to_tz_cached(0) {}
+ const char *func_name() const { return "convert_tz"; }
+ bool fix_length_and_dec()
+ {
+ fix_attributes_datetime(args[0]->datetime_precision(current_thd));
+ maybe_null= true;
+ return FALSE;
+ }
+ bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate);
+ void cleanup();
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_convert_tz>(thd, this); }
+};
+
+
+class Item_func_sec_to_time :public Item_timefunc
+{
+ bool check_arguments() const
+ { return args[0]->check_type_can_return_decimal(func_name()); }
+public:
+ Item_func_sec_to_time(THD *thd, Item *item): Item_timefunc(thd, item) {}
+ bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate);
+ bool fix_length_and_dec()
+ {
+ fix_attributes_time(args[0]->decimals);
+ maybe_null= true;
+ return FALSE;
+ }
+ const char *func_name() const { return "sec_to_time"; }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_sec_to_time>(thd, this); }
+};
+
+
+class Item_date_add_interval :public Item_handled_func
+{
+public:
+ const interval_type int_type; // keep it public
+ const bool date_sub_interval; // keep it public
+ Item_date_add_interval(THD *thd, Item *a, Item *b, interval_type type_arg,
+ bool neg_arg):
+ Item_handled_func(thd, a, b), int_type(type_arg),
+ date_sub_interval(neg_arg) {}
+ const char *func_name() const { return "date_add_interval"; }
+ bool fix_length_and_dec();
+ bool eq(const Item *item, bool binary_cmp) const;
+ void print(String *str, enum_query_type query_type);
+ enum precedence precedence() const { return INTERVAL_PRECEDENCE; }
+ bool need_parentheses_in_default() { return true; }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_date_add_interval>(thd, this); }
+};
+
+
+class Item_extract :public Item_int_func,
+ public Type_handler_hybrid_field_type
+{
+ date_mode_t m_date_mode;
+ const Type_handler_int_result *handler_by_length(uint32 length,
+ uint32 threashold)
+ {
+ if (length >= threashold)
+ return &type_handler_slonglong;
+ return &type_handler_slong;
+ }
+ void set_date_length(uint32 length)
+ {
+ /*
+ Although DATE components (e.g. YEAR, YEAR_MONTH, QUARTER, MONTH, WEEK)
+ cannot have a sign, we should probably still add +1,
+ because all around the code we assume that max_length is sign inclusive.
+ Another options is to set unsigned_flag to "true".
+ */
+ set_handler(handler_by_length(max_length= length, 10)); // QQ: see above
+ m_date_mode= date_mode_t(0);
+ }
+ void set_day_length(uint32 length)
+ {
+ /*
+ Units starting with DAY can be negative:
+ EXTRACT(DAY FROM '-24:00:00') -> -1
+ */
+ set_handler(handler_by_length(max_length= length + 1/*sign*/, 11));
+ m_date_mode= Temporal::Options(TIME_INTERVAL_DAY, current_thd);
+ }
+ void set_time_length(uint32 length)
+ {
+ set_handler(handler_by_length(max_length= length + 1/*sign*/, 11));
+ m_date_mode= Temporal::Options(TIME_INTERVAL_hhmmssff, current_thd);
+ }
+ public:
+ const interval_type int_type; // keep it public
+ Item_extract(THD *thd, interval_type type_arg, Item *a):
+ Item_int_func(thd, a),
+ Type_handler_hybrid_field_type(&type_handler_slonglong),
+ m_date_mode(date_mode_t(0)),
+ int_type(type_arg)
+ { }
+ const Type_handler *type_handler() const
+ {
+ return Type_handler_hybrid_field_type::type_handler();
+ }
+ longlong val_int();
+ enum Functype functype() const { return EXTRACT_FUNC; }
+ const char *func_name() const { return "extract"; }
+ bool check_arguments() const;
+ bool fix_length_and_dec();
+ bool eq(const Item *item, bool binary_cmp) const;
+ void print(String *str, enum_query_type query_type);
+ bool check_partition_func_processor(void *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(void *arg)
+ {
+ if (int_type != INTERVAL_WEEK)
+ return FALSE;
+ return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC);
+ }
+ bool check_valid_arguments_processor(void *int_arg)
+ {
+ switch (int_type) {
+ case INTERVAL_YEAR:
+ case INTERVAL_YEAR_MONTH:
+ case INTERVAL_QUARTER:
+ case INTERVAL_MONTH:
+ /* case INTERVAL_WEEK: Not allowed as partitioning function, bug#57071 */
+ case INTERVAL_DAY:
+ return !has_date_args();
+ case INTERVAL_DAY_HOUR:
+ case INTERVAL_DAY_MINUTE:
+ case INTERVAL_DAY_SECOND:
+ case INTERVAL_DAY_MICROSECOND:
+ return !has_datetime_args();
+ case INTERVAL_HOUR:
+ case INTERVAL_HOUR_MINUTE:
+ case INTERVAL_HOUR_SECOND:
+ case INTERVAL_MINUTE:
+ case INTERVAL_MINUTE_SECOND:
+ case INTERVAL_SECOND:
+ case INTERVAL_MICROSECOND:
+ case INTERVAL_HOUR_MICROSECOND:
+ case INTERVAL_MINUTE_MICROSECOND:
+ case INTERVAL_SECOND_MICROSECOND:
+ return !has_time_args();
+ default:
+ /*
+ INTERVAL_LAST is only an end marker,
+ INTERVAL_WEEK depends on default_week_format which is a session
+ variable and cannot be used for partitioning. See bug#57071.
+ */
+ break;
+ }
+ return true;
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_extract>(thd, this); }
+};
+
+
+class Item_char_typecast :public Item_handled_func
+{
+ uint cast_length;
+ CHARSET_INFO *cast_cs, *from_cs;
+ bool charset_conversion;
+ String tmp_value;
+ bool m_suppress_warning_to_error_escalation;
+public:
+ bool has_explicit_length() const { return cast_length != ~0U; }
+private:
+ String *reuse(String *src, size_t length);
+ String *copy(String *src, CHARSET_INFO *cs);
+ uint adjusted_length_with_warn(uint length);
+ void check_truncation_with_warn(String *src, size_t dstlen);
+ void fix_length_and_dec_internal(CHARSET_INFO *fromcs);
+public:
+ // Methods used by ColumnStore
+ uint get_cast_length() const { return cast_length; }
+public:
+ Item_char_typecast(THD *thd, Item *a, uint length_arg, CHARSET_INFO *cs_arg):
+ Item_handled_func(thd, a), cast_length(length_arg), cast_cs(cs_arg),
+ m_suppress_warning_to_error_escalation(false) {}
+ enum Functype functype() const { return CHAR_TYPECAST_FUNC; }
+ bool eq(const Item *item, bool binary_cmp) const;
+ const char *func_name() const { return "cast_as_char"; }
+ CHARSET_INFO *cast_charset() const { return cast_cs; }
+ String *val_str_generic(String *a);
+ String *val_str_binary_from_native(String *a);
+ void fix_length_and_dec_generic();
+ void fix_length_and_dec_numeric();
+ void fix_length_and_dec_str();
+ void fix_length_and_dec_native_to_binary(uint32 octet_length);
+ bool fix_length_and_dec()
+ {
+ return args[0]->type_handler()->Item_char_typecast_fix_length_and_dec(this);
+ }
+ void print(String *str, enum_query_type query_type);
+ bool need_parentheses_in_default() { return true; }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_char_typecast>(thd, this); }
+};
+
+
+class Item_interval_DDhhmmssff_typecast :public Item_char_typecast
+{
+ uint m_fsp;
+public:
+ Item_interval_DDhhmmssff_typecast(THD *thd, Item *a, uint fsp)
+ :Item_char_typecast(thd, a,Interval_DDhhmmssff::max_char_length(fsp),
+ &my_charset_latin1),
+ m_fsp(fsp)
+ { }
+ String *val_str(String *to)
+ {
+ Interval_DDhhmmssff it(current_thd, args[0], m_fsp);
+ null_value= !it.is_valid_interval_DDhhmmssff();
+ return it.to_string(to, m_fsp);
+ }
+};
+
+
+class Item_date_typecast :public Item_datefunc
+{
+public:
+ 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(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
+ bool fix_length_and_dec()
+ {
+ return args[0]->type_handler()->Item_date_typecast_fix_length_and_dec(this);
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_date_typecast>(thd, this); }
+};
+
+
+class Item_time_typecast :public Item_timefunc
+{
+public:
+ Item_time_typecast(THD *thd, Item *a, uint 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(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
+ bool fix_length_and_dec()
+ {
+ return args[0]->type_handler()->
+ Item_time_typecast_fix_length_and_dec(this);
+ }
+ Sql_mode_dependency value_depends_on_sql_mode() const;
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_time_typecast>(thd, this); }
+};
+
+
+class Item_datetime_typecast :public Item_datetimefunc
+{
+public:
+ Item_datetime_typecast(THD *thd, Item *a, uint dec_arg):
+ Item_datetimefunc(thd, a) { decimals= dec_arg; }
+ const char *func_name() const { return "cast_as_datetime"; }
+ void print(String *str, enum_query_type query_type)
+ {
+ print_cast_temporal(str, query_type);
+ }
+ bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
+ bool fix_length_and_dec()
+ {
+ return args[0]->type_handler()->
+ Item_datetime_typecast_fix_length_and_dec(this);
+ }
+ Sql_mode_dependency value_depends_on_sql_mode() const;
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_datetime_typecast>(thd, this); }
+};
+
+
+class Item_func_makedate :public Item_datefunc
+{
+ bool check_arguments() const
+ { return check_argument_types_can_return_int(0, arg_count); }
+public:
+ Item_func_makedate(THD *thd, Item *a, Item *b):
+ Item_datefunc(thd, a, b) {}
+ const char *func_name() const { return "makedate"; }
+ bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_makedate>(thd, this); }
+};
+
+
+class Item_func_timestamp :public Item_datetimefunc
+{
+ bool check_arguments() const
+ {
+ return args[0]->check_type_can_return_date(func_name()) ||
+ args[1]->check_type_can_return_time(func_name());
+ }
+public:
+ Item_func_timestamp(THD *thd, Item *a, Item *b)
+ :Item_datetimefunc(thd, a, b)
+ { }
+ const char *func_name() const { return "timestamp"; }
+ bool fix_length_and_dec()
+ {
+ THD *thd= current_thd;
+ uint dec0= args[0]->datetime_precision(thd);
+ uint dec1= Interval_DDhhmmssff::fsp(thd, args[1]);
+ fix_attributes_datetime(MY_MAX(dec0, dec1));
+ maybe_null= true;
+ return false;
+ }
+ bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
+ {
+ Datetime dt(thd, args[0], Datetime::Options(TIME_CONV_NONE, thd));
+ if (!dt.is_valid_datetime())
+ return null_value= true;
+ Interval_DDhhmmssff it(thd, args[1]);
+ if (!it.is_valid_interval_DDhhmmssff())
+ return null_value= true;
+ return (null_value= Sec6_add(dt.get_mysql_time(), it.get_mysql_time(), 1).
+ to_datetime(ltime));
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_timestamp>(thd, this); }
+};
+
+
+/**
+ ADDTIME(t,a) and SUBTIME(t,a) are time functions that calculate a
+ time/datetime value
+
+ t: time_or_datetime_expression
+ a: time_expression
+
+ Result: Time value or datetime value
+*/
+
+class Item_func_add_time :public Item_handled_func
+{
+ int sign;
+public:
+ // Methods used by ColumnStore
+ int get_sign() const { return sign; }
+public:
+ Item_func_add_time(THD *thd, Item *a, Item *b, bool neg_arg)
+ :Item_handled_func(thd, a, b), sign(neg_arg ? -1 : 1)
+ { }
+ bool fix_length_and_dec();
+ const char *func_name() const { return sign > 0 ? "addtime" : "subtime"; }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_add_time>(thd, this); }
+};
+
+
+class Item_func_timediff :public Item_timefunc
+{
+ bool check_arguments() const
+ { return check_argument_types_can_return_time(0, arg_count); }
+public:
+ Item_func_timediff(THD *thd, Item *a, Item *b): Item_timefunc(thd, a, b) {}
+ const char *func_name() const { return "timediff"; }
+ bool fix_length_and_dec()
+ {
+ THD *thd= current_thd;
+ uint dec= MY_MAX(args[0]->time_precision(thd),
+ args[1]->time_precision(thd));
+ fix_attributes_time(dec);
+ maybe_null= true;
+ return FALSE;
+ }
+ bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_timediff>(thd, this); }
+};
+
+class Item_func_maketime :public Item_timefunc
+{
+ bool check_arguments() const
+ {
+ return check_argument_types_can_return_int(0, 2) ||
+ args[2]->check_type_can_return_decimal(func_name());
+ }
+public:
+ Item_func_maketime(THD *thd, Item *a, Item *b, Item *c):
+ Item_timefunc(thd, a, b, c)
+ {}
+ bool fix_length_and_dec()
+ {
+ fix_attributes_time(args[2]->decimals);
+ maybe_null= true;
+ return FALSE;
+ }
+ const char *func_name() const { return "maketime"; }
+ bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_maketime>(thd, this); }
+};
+
+
+class Item_func_microsecond :public Item_long_func_time_field
+{
+public:
+ Item_func_microsecond(THD *thd, Item *a): Item_long_func_time_field(thd, a) {}
+ longlong val_int();
+ const char *func_name() const { return "microsecond"; }
+ bool fix_length_and_dec()
+ {
+ decimals=0;
+ maybe_null=1;
+ fix_char_length(6);
+ return FALSE;
+ }
+ bool check_partition_func_processor(void *int_arg) {return FALSE;}
+ bool check_vcol_func_processor(void *arg) { return FALSE;}
+ bool check_valid_arguments_processor(void *int_arg)
+ {
+ return !has_time_args();
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_microsecond>(thd, this); }
+};
+
+
+class Item_func_timestamp_diff :public Item_longlong_func
+{
+ bool check_arguments() const
+ { return check_argument_types_can_return_date(0, arg_count); }
+ const interval_type int_type;
+public:
+ // Methods used by ColumnStore
+ interval_type get_int_type() const { return int_type; };
+public:
+ Item_func_timestamp_diff(THD *thd, Item *a, Item *b, interval_type type_arg):
+ Item_longlong_func(thd, a, b), int_type(type_arg) {}
+ const char *func_name() const { return "timestampdiff"; }
+ longlong val_int();
+ bool fix_length_and_dec()
+ {
+ decimals=0;
+ maybe_null=1;
+ return FALSE;
+ }
+ virtual void print(String *str, enum_query_type query_type);
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_timestamp_diff>(thd, this); }
+};
+
+
+enum date_time_format
+{
+ USA_FORMAT, JIS_FORMAT, ISO_FORMAT, EUR_FORMAT, INTERNAL_FORMAT
+};
+
+class Item_func_get_format :public Item_str_ascii_func
+{
+public:
+ const timestamp_type type; // keep it public
+ Item_func_get_format(THD *thd, timestamp_type type_arg, Item *a):
+ Item_str_ascii_func(thd, a), type(type_arg)
+ {}
+ String *val_str_ascii(String *str);
+ const char *func_name() const { return "get_format"; }
+ bool fix_length_and_dec()
+ {
+ maybe_null= 1;
+ decimals=0;
+ fix_length_and_charset(17, default_charset());
+ return FALSE;
+ }
+ virtual void print(String *str, enum_query_type query_type);
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_get_format>(thd, this); }
+};
+
+
+class Item_func_str_to_date :public Item_handled_func
+{
+ bool const_item;
+ String subject_converter;
+ String format_converter;
+ CHARSET_INFO *internal_charset;
+public:
+ Item_func_str_to_date(THD *thd, Item *a, Item *b):
+ Item_handled_func(thd, a, b), const_item(false),
+ internal_charset(NULL)
+ {}
+ bool get_date_common(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate,
+ timestamp_type);
+ const char *func_name() const { return "str_to_date"; }
+ bool fix_length_and_dec();
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_str_to_date>(thd, this); }
+};
+
+
+class Item_func_last_day :public Item_datefunc
+{
+ bool check_arguments() const
+ { return args[0]->check_type_can_return_date(func_name()); }
+public:
+ Item_func_last_day(THD *thd, Item *a): Item_datefunc(thd, a) {}
+ const char *func_name() const { return "last_day"; }
+ bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate);
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_last_day>(thd, this); }
+};
+
+
+/*****************************************************************************/
+
+class Func_handler_date_add_interval
+{
+protected:
+ static uint interval_dec(const Item *item, interval_type int_type)
+ {
+ if (int_type == INTERVAL_MICROSECOND ||
+ (int_type >= INTERVAL_DAY_MICROSECOND &&
+ int_type <= INTERVAL_SECOND_MICROSECOND))
+ return TIME_SECOND_PART_DIGITS;
+ if (int_type == INTERVAL_SECOND && item->decimals > 0)
+ return MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS);
+ return 0;
+ }
+ interval_type int_type(const Item_handled_func *item) const
+ {
+ return static_cast<const Item_date_add_interval*>(item)->int_type;
+ }
+ bool sub(const Item_handled_func *item) const
+ {
+ return static_cast<const Item_date_add_interval*>(item)->date_sub_interval;
+ }
+ bool add(THD *thd, Item *item, interval_type type, bool sub, MYSQL_TIME *to) const
+ {
+ INTERVAL interval;
+ if (get_interval_value(thd, item, type, &interval))
+ return true;
+ if (sub)
+ interval.neg = !interval.neg;
+ return date_add_interval(thd, to, type, interval);
+ }
+};
+
+
+class Func_handler_date_add_interval_datetime:
+ public Item_handled_func::Handler_datetime,
+ public Func_handler_date_add_interval
+{
+public:
+ bool fix_length_and_dec(Item_handled_func *item) const
+ {
+ uint dec= MY_MAX(item->arguments()[0]->datetime_precision(current_thd),
+ interval_dec(item->arguments()[1], int_type(item)));
+ item->fix_attributes_datetime(dec);
+ return false;
+ }
+ bool get_date(THD *thd, Item_handled_func *item,
+ MYSQL_TIME *to, date_mode_t fuzzy) const
+ {
+ Datetime::Options opt(TIME_CONV_NONE, thd);
+ Datetime dt(thd, item->arguments()[0], opt);
+ if (!dt.is_valid_datetime() ||
+ dt.check_date_with_warn(thd, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE))
+ return (item->null_value= true);
+ dt.copy_to_mysql_time(to);
+ return (item->null_value= add(thd, item->arguments()[1],
+ int_type(item), sub(item), to));
+ }
+};
+
+
+class Func_handler_date_add_interval_datetime_arg0_time:
+ public Func_handler_date_add_interval_datetime
+{
+public:
+ bool get_date(THD *thd, Item_handled_func *item,
+ MYSQL_TIME *to, date_mode_t fuzzy) const;
+};
+
+
+class Func_handler_date_add_interval_date:
+ public Item_handled_func::Handler_date,
+ public Func_handler_date_add_interval
+{
+public:
+ bool get_date(THD *thd, Item_handled_func *item,
+ MYSQL_TIME *to, date_mode_t fuzzy) const
+ {
+ /*
+ The first argument is known to be of the DATE data type (not DATETIME).
+ We don't need rounding here.
+ */
+ Date d(thd, item->arguments()[0], TIME_CONV_NONE);
+ if (!d.is_valid_date() ||
+ d.check_date_with_warn(thd, TIME_NO_ZERO_DATE | TIME_NO_ZERO_IN_DATE))
+ return (item->null_value= true);
+ d.copy_to_mysql_time(to);
+ return (item->null_value= add(thd, item->arguments()[1],
+ int_type(item), sub(item), to));
+ }
+};
+
+
+class Func_handler_date_add_interval_time:
+ public Item_handled_func::Handler_time,
+ public Func_handler_date_add_interval
+{
+public:
+ bool fix_length_and_dec(Item_handled_func *item) const
+ {
+ uint dec= MY_MAX(item->arguments()[0]->time_precision(current_thd),
+ interval_dec(item->arguments()[1], int_type(item)));
+ item->fix_attributes_time(dec);
+ return false;
+ }
+ bool get_date(THD *thd, Item_handled_func *item,
+ MYSQL_TIME *to, date_mode_t fuzzy) const
+ {
+ Time t(thd, item->arguments()[0]);
+ if (!t.is_valid_time())
+ return (item->null_value= true);
+ t.copy_to_mysql_time(to);
+ return (item->null_value= add(thd, item->arguments()[1],
+ int_type(item), sub(item), to));
+ }
+};
+
+
+class Func_handler_date_add_interval_string:
+ public Item_handled_func::Handler_temporal_string,
+ public Func_handler_date_add_interval
+{
+public:
+ bool fix_length_and_dec(Item_handled_func *item) const
+ {
+ uint dec= MY_MAX(item->arguments()[0]->datetime_precision(current_thd),
+ interval_dec(item->arguments()[1], int_type(item)));
+ item->Type_std_attributes::set(
+ Type_temporal_attributes_not_fixed_dec(MAX_DATETIME_WIDTH, dec, false),
+ DTCollation(item->default_charset(),
+ DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII));
+ item->fix_char_length(item->max_length);
+ return false;
+ }
+ bool get_date(THD *thd, Item_handled_func *item,
+ MYSQL_TIME *to, date_mode_t fuzzy) const
+ {
+ if (item->arguments()[0]->
+ get_date(thd, to, Datetime::Options(TIME_CONV_NONE, thd)) ||
+ (to->time_type != MYSQL_TIMESTAMP_TIME &&
+ check_date_with_warn(thd, to, TIME_NO_ZEROS, MYSQL_TIMESTAMP_ERROR)))
+ return (item->null_value= true);
+ return (item->null_value= add(thd, item->arguments()[1],
+ int_type(item), sub(item), to));
+ }
+};
+
+
+class Func_handler_sign
+{
+protected:
+ int m_sign;
+ Func_handler_sign(int sign) :m_sign(sign) { }
+};
+
+
+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_sign(sign)
+ { }
+ bool fix_length_and_dec(Item_handled_func *item) const
+ {
+ THD *thd= current_thd;
+ uint dec0= item->arguments()[0]->datetime_precision(thd);
+ uint dec1= Interval_DDhhmmssff::fsp(thd, item->arguments()[1]);
+ item->fix_attributes_datetime(MY_MAX(dec0, dec1));
+ return false;
+ }
+ bool get_date(THD *thd, Item_handled_func *item,
+ MYSQL_TIME *to, date_mode_t fuzzy) const
+ {
+ DBUG_ASSERT(item->is_fixed());
+ Datetime::Options opt(TIME_CONV_NONE, thd);
+ Datetime dt(thd, item->arguments()[0], opt);
+ if (!dt.is_valid_datetime())
+ return item->null_value= true;
+ Interval_DDhhmmssff it(thd, item->arguments()[1]);
+ if (!it.is_valid_interval_DDhhmmssff())
+ return item->null_value= true;
+ return (item->null_value= (Sec6_add(dt.get_mysql_time(),
+ it.get_mysql_time(), m_sign).
+ to_datetime(to)));
+ }
+};
+
+
+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_sign(sign)
+ { }
+ bool fix_length_and_dec(Item_handled_func *item) const
+ {
+ THD *thd= current_thd;
+ uint dec0= item->arguments()[0]->time_precision(thd);
+ uint dec1= Interval_DDhhmmssff::fsp(thd, item->arguments()[1]);
+ item->fix_attributes_time(MY_MAX(dec0, dec1));
+ return false;
+ }
+ bool get_date(THD *thd, Item_handled_func *item,
+ MYSQL_TIME *to, date_mode_t fuzzy) const
+ {
+ DBUG_ASSERT(item->is_fixed());
+ Time t(thd, item->arguments()[0]);
+ if (!t.is_valid_time())
+ return item->null_value= true;
+ Interval_DDhhmmssff i(thd, item->arguments()[1]);
+ if (!i.is_valid_interval_DDhhmmssff())
+ return item->null_value= true;
+ return (item->null_value= (Sec6_add(t.get_mysql_time(),
+ i.get_mysql_time(), m_sign).
+ to_time(thd, to, item->decimals)));
+ }
+};
+
+
+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_sign(sign)
+ { }
+ bool fix_length_and_dec(Item_handled_func *item) const
+ {
+ uint dec0= item->arguments()[0]->decimals;
+ uint dec1= Interval_DDhhmmssff::fsp(current_thd, item->arguments()[1]);
+ uint dec= MY_MAX(dec0, dec1);
+ item->Type_std_attributes::set(
+ Type_temporal_attributes_not_fixed_dec(MAX_DATETIME_WIDTH, dec, false),
+ DTCollation(item->default_charset(),
+ DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII));
+ item->fix_char_length(item->max_length);
+ return false;
+ }
+ bool get_date(THD *thd, Item_handled_func *item,
+ MYSQL_TIME *to, date_mode_t fuzzy) const
+ {
+ DBUG_ASSERT(item->is_fixed());
+ // Detect a proper timestamp type based on the argument values
+ Temporal_hybrid l_time1(thd, item->arguments()[0],
+ Temporal::Options(TIME_TIME_ONLY, thd));
+ if (!l_time1.is_valid_temporal())
+ return (item->null_value= true);
+ Interval_DDhhmmssff l_time2(thd, item->arguments()[1]);
+ if (!l_time2.is_valid_interval_DDhhmmssff())
+ return (item->null_value= true);
+ Sec6_add add(l_time1.get_mysql_time(), l_time2.get_mysql_time(), m_sign);
+ return (item->null_value= (l_time1.get_mysql_time()->time_type ==
+ MYSQL_TIMESTAMP_TIME ?
+ add.to_time(thd, to, item->decimals) :
+ add.to_datetime(to)));
+ }
+};
+
+
+class Func_handler_str_to_date_datetime_sec:
+ public Item_handled_func::Handler_datetime
+{
+public:
+ bool fix_length_and_dec(Item_handled_func *item) const
+ {
+ item->fix_attributes_datetime(0);
+ return false;
+ }
+ bool get_date(THD *thd, Item_handled_func *item,
+ MYSQL_TIME *to, date_mode_t fuzzy) const
+ {
+ return static_cast<Item_func_str_to_date*>(item)->
+ get_date_common(thd, to, fuzzy, MYSQL_TIMESTAMP_DATETIME);
+ }
+};
+
+
+class Func_handler_str_to_date_datetime_usec:
+ public Item_handled_func::Handler_datetime
+{
+public:
+ bool fix_length_and_dec(Item_handled_func *item) const
+ {
+ item->fix_attributes_datetime(TIME_SECOND_PART_DIGITS);
+ return false;
+ }
+ bool get_date(THD *thd, Item_handled_func *item,
+ MYSQL_TIME *to, date_mode_t fuzzy) const
+ {
+ return static_cast<Item_func_str_to_date*>(item)->
+ get_date_common(thd, to, fuzzy, MYSQL_TIMESTAMP_DATETIME);
+ }
+};
+
+
+class Func_handler_str_to_date_date: public Item_handled_func::Handler_date
+{
+public:
+ bool get_date(THD *thd, Item_handled_func *item,
+ MYSQL_TIME *to, date_mode_t fuzzy) const
+ {
+ return static_cast<Item_func_str_to_date*>(item)->
+ get_date_common(thd, to, fuzzy, MYSQL_TIMESTAMP_DATE);
+ }
+};
+
+
+class Func_handler_str_to_date_time: public Item_handled_func::Handler_time
+{
+public:
+ bool get_date(THD *thd, Item_handled_func *item,
+ MYSQL_TIME *to, date_mode_t fuzzy) const
+ {
+ if (static_cast<Item_func_str_to_date*>(item)->
+ get_date_common(thd, to, fuzzy, MYSQL_TIMESTAMP_TIME))
+ return true;
+ if (to->day)
+ {
+ /*
+ Day part for time type can be nonzero value and so
+ we should add hours from day part to hour part to
+ keep valid time value.
+ */
+ to->hour+= to->day * 24;
+ to->day= 0;
+ }
+ return false;
+ }
+};
+
+
+class Func_handler_str_to_date_time_sec: public Func_handler_str_to_date_time
+{
+public:
+ bool fix_length_and_dec(Item_handled_func *item) const
+ {
+ item->fix_attributes_time(0);
+ return false;
+ }
+};
+
+
+class Func_handler_str_to_date_time_usec: public Func_handler_str_to_date_time
+{
+public:
+ bool fix_length_and_dec(Item_handled_func *item) const
+ {
+ item->fix_attributes_time(TIME_SECOND_PART_DIGITS);
+ return false;
+ }
+};
+
+
+#endif /* ITEM_TIMEFUNC_INCLUDED */