summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/item.cc119
-rw-r--r--sql/item.h81
-rw-r--r--sql/item_func.h130
-rw-r--r--sql/item_timefunc.cc36
-rw-r--r--sql/item_timefunc.h243
-rw-r--r--sql/sql_type.cc51
-rw-r--r--sql/sql_type.h169
-rw-r--r--storage/connect/ha_connect.cc2
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(&ltime) ||
- str->alloc(MAX_DATE_STRING_REP_LENGTH))
- {
- null_value= 1;
- return (String *) 0;
- }
- str->length(my_TIME_to_str(&ltime, 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(&ltime))
- {
- my_decimal_set_zero(decimal_value);
- null_value= 1; // set NULL, stop processing
- return 0;
- }
- return date2my_decimal(&ltime, decimal_value);
-}
-
-
-my_decimal *Item::val_decimal_from_time(my_decimal *decimal_value)
-{
- DBUG_ASSERT(is_fixed());
- MYSQL_TIME ltime;
- if (get_time(&ltime))
- {
- my_decimal_set_zero(decimal_value);
- return 0;
- }
- return date2my_decimal(&ltime, decimal_value);
-}
-
-
-longlong Item::val_int_from_date()
-{
- DBUG_ASSERT(is_fixed());
- MYSQL_TIME ltime;
- if (get_temporal_with_sql_mode(&ltime))
- return 0;
- longlong v= TIME_to_ulonglong(&ltime);
- return ltime.neg ? -v : v;
-}
-
-
-double Item::val_real_from_date()
-{
- DBUG_ASSERT(is_fixed());
- MYSQL_TIME ltime;
- if (get_temporal_with_sql_mode(&ltime))
- return 0;
- return TIME_to_double(&ltime);
-}
-
-
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, &ltime, 0) ||
- (item->null_value= my_TIME_to_str(&ltime, 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;