summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc17
-rw-r--r--sql/field.h8
-rw-r--r--sql/item.cc59
-rw-r--r--sql/item.h31
-rw-r--r--sql/item_func.cc35
-rw-r--r--sql/item_func.h37
-rw-r--r--sql/item_sum.h6
-rw-r--r--sql/item_timefunc.h2
-rw-r--r--sql/my_decimal.h2
-rw-r--r--sql/procedure.h2
-rw-r--r--sql/sql_error.h55
-rw-r--r--sql/sql_time.cc83
-rw-r--r--sql/sql_type.cc203
-rw-r--r--sql/sql_type.h306
-rw-r--r--sql/sql_type_int.h12
15 files changed, 510 insertions, 348 deletions
diff --git a/sql/field.cc b/sql/field.cc
index d7214687e2d..7e27ed1bfc3 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -2253,16 +2253,13 @@ uint Field::fill_cache_field(CACHE_FIELD *copy)
}
-bool Field::get_date(MYSQL_TIME *ltime,date_mode_t fuzzydate)
-{
- char buff[40];
- String tmp(buff,sizeof(buff),&my_charset_bin),*res;
- if (!(res=val_str(&tmp)) ||
- str_to_datetime_with_warn(get_thd(),
- res->charset(), res->ptr(), res->length(),
- ltime, fuzzydate))
- return 1;
- return 0;
+bool Field::get_date(MYSQL_TIME *to, date_mode_t mode)
+{
+ StringBuffer<40> tmp;
+ Temporal::Warn_push warn(get_thd(), NullS, to, mode);
+ Temporal_hybrid *t= new(to) Temporal_hybrid(get_thd(), &warn,
+ val_str(&tmp), mode);
+ return !t->is_valid_temporal();
}
/**
diff --git a/sql/field.h b/sql/field.h
index d5b2a621d48..eb39b6bcec9 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -2077,8 +2077,9 @@ public:
}
bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate)
{
- return my_decimal(ptr, precision, dec).
- to_datetime_with_warn(get_thd(), ltime, fuzzydate, field_name.str);
+ my_decimal nr(ptr, precision, dec);
+ return decimal_to_datetime_with_warn(get_thd(), &nr, ltime,
+ fuzzydate, field_name.str);
}
bool val_bool()
{
@@ -2612,9 +2613,10 @@ protected:
int store_invalid_with_warning(const ErrConv *str, int was_cut,
timestamp_type ts_type)
{
+ DBUG_ASSERT(was_cut);
reset();
Sql_condition::enum_warning_level level= Sql_condition::WARN_LEVEL_WARN;
- if (was_cut == 0) // special case: zero date
+ if (was_cut & MYSQL_TIME_WARN_ZERO_DATE)
{
DBUG_ASSERT(ts_type != MYSQL_TIMESTAMP_TIME);
set_warnings(level, str, MYSQL_TIME_WARN_OUT_OF_RANGE, ts_type);
diff --git a/sql/item.cc b/sql/item.cc
index 88bb929fc05..d4cfa790986 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1277,60 +1277,27 @@ Item *Item_param::safe_charset_converter(THD *thd, CHARSET_INFO *tocs)
bool Item::get_date_from_int(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
{
Longlong_hybrid value(val_int(), unsigned_flag);
- if (null_value || int_to_datetime_with_warn(thd, value,
- ltime, fuzzydate,
- field_name_or_null()))
- return null_value|= make_zero_date(ltime, fuzzydate);
- return null_value= false;
+ return null_value || int_to_datetime_with_warn(thd, value,
+ ltime, fuzzydate,
+ field_name_or_null());
}
bool Item::get_date_from_real(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
{
double value= val_real();
- if (null_value || double_to_datetime_with_warn(thd, value, ltime, fuzzydate,
- field_name_or_null()))
- return null_value|= make_zero_date(ltime, fuzzydate);
- return null_value= false;
+ return null_value || double_to_datetime_with_warn(thd, value,
+ ltime, fuzzydate,
+ field_name_or_null());
}
-bool Item::get_date_from_string(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
+bool Item::get_date_from_string(THD *thd, MYSQL_TIME *to, date_mode_t mode)
{
- char buff[40];
- String tmp(buff,sizeof(buff), &my_charset_bin),*res;
- if (!(res=val_str(&tmp)) ||
- str_to_datetime_with_warn(thd, res->charset(), res->ptr(), res->length(),
- ltime, fuzzydate))
- return null_value|= make_zero_date(ltime, fuzzydate);
- return null_value= false;
-}
-
-
-bool Item::make_zero_date(MYSQL_TIME *ltime, date_mode_t fuzzydate)
-{
- /*
- if the item was not null and convertion failed, we return a zero date
- if allowed, otherwise - null.
- */
- bzero((char*) ltime,sizeof(*ltime));
- if (fuzzydate & TIME_TIME_ONLY)
- {
- /*
- In the following scenario:
- - The caller expected to get a TIME value
- - Item returned a not NULL string or numeric value
- - But then conversion from string or number to TIME failed
- we need to change the default time_type from MYSQL_TIMESTAMP_DATE
- (which was set in bzero) to MYSQL_TIMESTAMP_TIME and therefore
- return TIME'00:00:00' rather than DATE'0000-00-00'.
- If we don't do this, methods like Item::get_time_with_conversion()
- will erroneously subtract CURRENT_DATE from '0000-00-00 00:00:00'
- and return TIME'-838:59:59' instead of TIME'00:00:00' as a result.
- */
- ltime->time_type= MYSQL_TIMESTAMP_TIME;
- }
- return !(fuzzydate & TIME_FUZZY_DATES);
+ StringBuffer<40> tmp;
+ Temporal::Warn_push warn(thd, field_name_or_null(), to, mode);
+ Temporal_hybrid *t= new(to) Temporal_hybrid(thd, &warn, val_str(&tmp), mode);
+ return !t->is_valid_temporal();
}
@@ -3735,7 +3702,7 @@ my_decimal *Item_null::val_decimal(my_decimal *decimal_value)
bool Item_null::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
{
- make_zero_date(ltime, fuzzydate);
+ set_zero_time(ltime, MYSQL_TIMESTAMP_NONE);
return (null_value= true);
}
@@ -4261,7 +4228,7 @@ bool Item_param::get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate)
*res= value.time;
return 0;
}
- return type_handler()->Item_get_date(thd, this, res, fuzzydate);
+ return type_handler()->Item_get_date_with_warn(thd, this, res, fuzzydate);
}
diff --git a/sql/item.h b/sql/item.h
index d15dbade60f..c2666c35c67 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -870,12 +870,6 @@ protected:
return rc;
}
public:
- /*
- This method is used if the item was not null but convertion to
- TIME/DATE/DATETIME failed. We return a zero date if allowed,
- otherwise - null.
- */
- bool make_zero_date(MYSQL_TIME *ltime, date_mode_t fuzzydate);
/*
Cache val_str() into the own buffer, e.g. to evaluate constant
@@ -1172,6 +1166,12 @@ public:
If value is not null null_value flag will be reset to FALSE.
*/
virtual double val_real()=0;
+ Double_null to_double_null()
+ {
+ // val_real() must be caleed on a separate line. See to_longlong_null()
+ double nr= val_real();
+ return Double_null(nr, null_value);
+ }
/*
Return integer representation of item.
@@ -1193,6 +1193,10 @@ public:
*/
return Longlong_null(nr, null_value);
}
+ Longlong_hybrid_null to_longlong_hybrid_null()
+ {
+ return Longlong_hybrid_null(to_longlong_null(), unsigned_flag);
+ }
/**
Get a value for CAST(x AS SIGNED).
Too large positive unsigned integer values are converted
@@ -3031,7 +3035,7 @@ public:
Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs);
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
{
- return type_handler()->Item_get_date(thd, this, ltime, fuzzydate);
+ return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate);
}
};
@@ -4516,7 +4520,7 @@ public:
String *val_str(String*) { return &str_value; }
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
{
- return type_handler()->Item_get_date(thd, this, ltime, fuzzydate);
+ return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate);
}
};
@@ -6389,10 +6393,9 @@ class Item_cache_year: public Item_cache_int
public:
Item_cache_year(THD *thd, const Type_handler *handler)
:Item_cache_int(thd, handler) { }
- bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
+ bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t mode)
{
- return null_value=
- VYear(this).to_mysql_time_with_warn(thd, ltime, fuzzydate, NULL);
+ return type_handler_year.Item_get_date_with_warn(thd, this, to, mode);
}
};
@@ -6549,8 +6552,10 @@ public:
longlong val_int();
String* val_str(String *str);
my_decimal *val_decimal(my_decimal *);
- bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
- { return VDec(this).to_datetime_with_warn(thd, ltime, fuzzydate, this); }
+ bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t mode)
+ {
+ return decimal_to_datetime_with_warn(thd, VDec(this).ptr(), to, mode, NULL);
+ }
bool cache_value();
Item *convert_to_basic_const_item(THD *thd);
Item *get_copy(THD *thd)
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 20c0a2564bb..c176a7e43a7 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -831,17 +831,6 @@ Item_func_hybrid_field_type::val_decimal_from_int_op(my_decimal *dec)
return dec;
}
-bool Item_func_hybrid_field_type::get_date_from_int_op(THD *thd,
- MYSQL_TIME *ltime,
- date_mode_t fuzzydate)
-{
- Longlong_hybrid value(int_op(), unsigned_flag);
- if (null_value || int_to_datetime_with_warn(thd, value,
- ltime, fuzzydate, NULL))
- return make_zero_mysql_time(ltime, fuzzydate);
- return (null_value= 0);
-}
-
String *Item_func_hybrid_field_type::val_str_from_real_op(String *str)
{
@@ -867,17 +856,6 @@ Item_func_hybrid_field_type::val_decimal_from_real_op(my_decimal *dec)
return dec;
}
-bool Item_func_hybrid_field_type::get_date_from_real_op(THD *thd,
- MYSQL_TIME *ltime,
- date_mode_t fuzzydate)
-{
- double value= real_op();
- if (null_value ||
- double_to_datetime_with_warn(thd, value, ltime, fuzzydate, NULL))
- return make_zero_mysql_time(ltime, fuzzydate);
- return (null_value= 0);
-}
-
String *Item_func_hybrid_field_type::val_str_from_date_op(String *str)
{
@@ -975,19 +953,6 @@ Item_func_hybrid_field_type::val_decimal_from_str_op(my_decimal *decimal_value)
return res ? decimal_from_string_with_check(decimal_value, res) : 0;
}
-bool Item_func_hybrid_field_type::get_date_from_str_op(THD *thd,
- MYSQL_TIME *ltime,
- date_mode_t fuzzydate)
-{
- StringBuffer<40> tmp;
- String *res;
- if (!(res= str_op_with_null_check(&tmp)) ||
- str_to_datetime_with_warn(thd, res->charset(), res->ptr(), res->length(),
- ltime, fuzzydate))
- return make_zero_mysql_time(ltime, fuzzydate);
- return (null_value= 0);
-}
-
void Item_func_signed::print(String *str, enum_query_type query_type)
{
diff --git a/sql/item_func.h b/sql/item_func.h
index 602b13fad7a..660d39f48ea 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -680,11 +680,6 @@ class Item_func_hybrid_field_type: public Item_hybrid_func
DBUG_ASSERT((res != NULL) ^ null_value);
return res;
}
- bool make_zero_mysql_time(MYSQL_TIME *ltime, date_mode_t fuzzydate)
- {
- bzero(ltime, sizeof(*ltime));
- return null_value|= !(fuzzydate & TIME_FUZZY_DATES);
- }
public:
// Value methods that involve no conversion
@@ -723,10 +718,6 @@ public:
double val_real_from_time_op();
double val_real_from_int_op();
- bool get_date_from_str_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
- bool get_date_from_real_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
- bool get_date_from_int_op(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
-
public:
Item_func_hybrid_field_type(THD *thd):
Item_hybrid_func(thd)
@@ -770,11 +761,11 @@ public:
DBUG_ASSERT(null_value == (res == NULL));
return res;
}
- bool get_date(THD *thd, MYSQL_TIME *res, date_mode_t fuzzydate)
+ bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t mode)
{
DBUG_ASSERT(fixed);
return Item_func_hybrid_field_type::type_handler()->
- Item_func_hybrid_field_type_get_date(thd, this, res, fuzzydate);
+ Item_func_hybrid_field_type_get_date_with_warn(thd, this, to, mode);
}
/**
@@ -794,6 +785,10 @@ public:
*/
return Longlong_null(nr, null_value);
}
+ Longlong_hybrid_null to_longlong_hybrid_null_op()
+ {
+ return Longlong_hybrid_null(to_longlong_null_op(), unsigned_flag);
+ }
/**
@brief Performs the operation that this functions implements when the
@@ -802,6 +797,12 @@ public:
@return The result of the operation.
*/
virtual double real_op()= 0;
+ Double_null to_double_null_op()
+ {
+ // val_real() must be caleed on a separate line. See to_longlong_null()
+ double nr= real_op();
+ return Double_null(nr, null_value);
+ }
/**
@brief Performs the operation that this functions implements when the
@@ -1180,8 +1181,10 @@ public:
double val_real() { return VDec(this).to_double(); }
longlong val_int() { return VDec(this).to_longlong(unsigned_flag); }
my_decimal *val_decimal(my_decimal*);
- bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
- { return VDec(this).to_datetime_with_warn(thd, ltime, fuzzydate, this); }
+ bool get_date(THD *thd, MYSQL_TIME *to, date_mode_t mode)
+ {
+ return decimal_to_datetime_with_warn(thd, VDec(this).ptr(), to, mode, NULL);
+ }
const Type_handler *type_handler() const { return &type_handler_newdecimal; }
void fix_length_and_dec_generic() {}
bool fix_length_and_dec()
@@ -2292,7 +2295,7 @@ public:
}
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
{
- return type_handler()->Item_get_date(thd, this, ltime, fuzzydate);
+ return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate);
}
};
@@ -2602,7 +2605,9 @@ public:
{ return create_table_field_from_handler(table); }
bool check_vcol_func_processor(void *arg);
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
- { return type_handler()->Item_get_date(thd, this, ltime, fuzzydate); }
+ {
+ return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate);
+ }
};
@@ -2832,7 +2837,7 @@ public:
{ return val_decimal_from_real(dec_buf); }
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
{
- return type_handler()->Item_get_date(thd, this, ltime, fuzzydate);
+ return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate);
}
/* TODO: fix to support views */
const char *func_name() const { return "get_system_var"; }
diff --git a/sql/item_sum.h b/sql/item_sum.h
index c88a850c241..1a21c257221 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -744,7 +744,7 @@ public:
my_decimal *val_decimal(my_decimal *);
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
{
- return type_handler()->Item_get_date(thd, this, ltime, fuzzydate);
+ return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate);
}
void reset_field();
};
@@ -1405,7 +1405,7 @@ public:
}
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
{
- return type_handler()->Item_get_date(thd, this, ltime, fuzzydate);
+ return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate);
}
};
@@ -1567,7 +1567,7 @@ public:
virtual void print(String *str, enum_query_type query_type);
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
{
- return type_handler()->Item_get_date(thd, this, ltime, fuzzydate);
+ return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate);
}
};
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index de5ba8df2fe..d2a4e87a3d1 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -457,7 +457,7 @@ public:
}
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
{
- return type_handler()->Item_get_date(thd, this, ltime, fuzzydate);
+ return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate);
}
const Type_handler *type_handler() const { return &type_handler_long; }
bool fix_length_and_dec()
diff --git a/sql/my_decimal.h b/sql/my_decimal.h
index f0bb69c60c8..b22c686cc90 100644
--- a/sql/my_decimal.h
+++ b/sql/my_decimal.h
@@ -217,8 +217,6 @@ public:
{
return check_result(mask, decimal_round(this, to, (int) scale, mode));
}
- bool to_datetime_with_warn(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate,
- const char *field_name);
int to_binary(uchar *bin, int prec, int scale,
uint mask= E_DEC_FATAL_ERROR) const;
#endif
diff --git a/sql/procedure.h b/sql/procedure.h
index 2169091c0a6..050cc3817c0 100644
--- a/sql/procedure.h
+++ b/sql/procedure.h
@@ -71,7 +71,7 @@ public:
}
bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate)
{
- return type_handler()->Item_get_date(thd, this, ltime, fuzzydate);
+ return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate);
}
Item* get_copy(THD *thd) { return 0; }
};
diff --git a/sql/sql_error.h b/sql/sql_error.h
index b783d527cb3..6586c49a125 100644
--- a/sql/sql_error.h
+++ b/sql/sql_error.h
@@ -814,11 +814,48 @@ private:
extern char *err_conv(char *buff, uint to_length, const char *from,
uint from_length, CHARSET_INFO *from_cs);
-class ErrConv
+class ErrBuff
{
protected:
mutable char err_buffer[MYSQL_ERRMSG_SIZE];
public:
+ ErrBuff()
+ {
+ err_buffer[0]= '\0';
+ }
+ const char *ptr() const { return err_buffer; }
+ const char *set_longlong(const Longlong_hybrid &nr) const
+ {
+ return nr.is_unsigned() ? ullstr(nr.value(), err_buffer) :
+ llstr(nr.value(), err_buffer);
+ }
+ const char *set_double(double nr) const
+ {
+ my_gcvt(nr, MY_GCVT_ARG_DOUBLE, sizeof(err_buffer), err_buffer, 0);
+ return err_buffer;
+ }
+ const char *set_decimal(const decimal_t *d) const
+ {
+ int len= sizeof(err_buffer);
+ decimal2string(d, err_buffer, &len, 0, 0, ' ');
+ return err_buffer;
+ }
+ const char *set_str(const char *str, size_t len, CHARSET_INFO *cs) const
+ {
+ DBUG_ASSERT(len < UINT_MAX32);
+ return err_conv(err_buffer, (uint) sizeof(err_buffer), str, (uint) len, cs);
+ }
+ const char *set_mysql_time(const MYSQL_TIME *ltime) const
+ {
+ my_TIME_to_str(ltime, err_buffer, AUTO_SEC_PART_DIGITS);
+ return err_buffer;
+ }
+};
+
+
+class ErrConv: public ErrBuff
+{
+public:
ErrConv() {}
virtual ~ErrConv() {}
virtual const char *ptr() const = 0;
@@ -838,8 +875,7 @@ public:
: ErrConv(), str(s->ptr()), len(s->length()), cs(s->charset()) {}
const char *ptr() const
{
- DBUG_ASSERT(len < UINT_MAX32);
- return err_conv(err_buffer, (uint) sizeof(err_buffer), str, (uint) len, cs);
+ return set_str(str, len, cs);
}
};
@@ -850,8 +886,7 @@ public:
: ErrConv(), Longlong_hybrid(nr) { }
const char *ptr() const
{
- return m_unsigned ? ullstr(m_value, err_buffer) :
- llstr(m_value, err_buffer);
+ return set_longlong(static_cast<Longlong_hybrid>(*this));
}
};
@@ -862,8 +897,7 @@ public:
ErrConvDouble(double num_arg) : ErrConv(), num(num_arg) {}
const char *ptr() const
{
- my_gcvt(num, MY_GCVT_ARG_DOUBLE, sizeof(err_buffer), err_buffer, 0);
- return err_buffer;
+ return set_double(num);
}
};
@@ -874,8 +908,7 @@ public:
ErrConvTime(const MYSQL_TIME *ltime_arg) : ErrConv(), ltime(ltime_arg) {}
const char *ptr() const
{
- my_TIME_to_str(ltime, err_buffer, AUTO_SEC_PART_DIGITS);
- return err_buffer;
+ return set_mysql_time(ltime);
}
};
@@ -886,9 +919,7 @@ public:
ErrConvDecimal(const decimal_t *d_arg) : ErrConv(), d(d_arg) {}
const char *ptr() const
{
- int len= sizeof(err_buffer);
- decimal2string(d, err_buffer, &len, 0, 0, ' ');
- return err_buffer;
+ return set_decimal(d);
}
};
diff --git a/sql/sql_time.cc b/sql/sql_time.cc
index 630d150be77..9562394f11e 100644
--- a/sql/sql_time.cc
+++ b/sql/sql_time.cc
@@ -377,9 +377,11 @@ bool Temporal::str_to_time(MYSQL_TIME_STATUS *status,
date_mode_t fuzzydate)
{
TemporalAsciiBuffer tmp(str, length, cs);
- return ::str_to_time(tmp.str, tmp.length, this,
+ bool rc= ::str_to_time(tmp.str, tmp.length, this,
ulonglong(fuzzydate & TIME_MODE_FOR_XXX_TO_DATE),
status);
+ DBUG_ASSERT(status->warnings || !rc);
+ return rc;
}
@@ -389,9 +391,11 @@ bool Temporal::str_to_datetime(MYSQL_TIME_STATUS *status,
date_mode_t flags)
{
TemporalAsciiBuffer tmp(str, length, cs);
- return ::str_to_datetime(tmp.str, tmp.length, this,
+ bool rc= ::str_to_datetime(tmp.str, tmp.length, this,
ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE),
status);
+ DBUG_ASSERT(status->warnings || !rc);
+ return rc;
}
@@ -401,7 +405,9 @@ bool Interval_DDhhmmssff::str_to_DDhhmmssff(MYSQL_TIME_STATUS *status,
CHARSET_INFO *cs, ulong max_hour)
{
TemporalAsciiBuffer tmp(str, length, cs);
- return ::str_to_DDhhmmssff(tmp.str, tmp.length, this, UINT_MAX32, status);
+ bool rc= ::str_to_DDhhmmssff(tmp.str, tmp.length, this, UINT_MAX32, status);
+ DBUG_ASSERT(status->warnings || !rc);
+ return rc;
}
@@ -413,45 +419,22 @@ bool Interval_DDhhmmssff::str_to_DDhhmmssff(MYSQL_TIME_STATUS *status,
See description of str_to_datetime() for more information.
*/
-static bool
-str_to_datetime_with_warn(THD *thd, CHARSET_INFO *cs,
- const char *str, size_t length, MYSQL_TIME *l_time,
- date_mode_t flags, MYSQL_TIME_STATUS *status)
-{
- Temporal_hybrid *t= new(l_time) Temporal_hybrid(status, str, length, cs, flags);
- if (!t->is_valid_temporal() || status->warnings)
- {
- const ErrConvString err(str, length, &my_charset_bin);
- make_truncated_value_warning(thd,
- !t->is_valid_temporal() ?
- Sql_condition::WARN_LEVEL_WARN :
- Sql_condition::time_warn_level(status->warnings),
- &err, flags & TIME_TIME_ONLY ?
- MYSQL_TIMESTAMP_TIME : l_time->time_type, NullS);
- }
- DBUG_EXECUTE_IF("str_to_datetime_warn",
- push_warning(thd, Sql_condition::WARN_LEVEL_NOTE,
- ER_YES, str););
- return !t->is_valid_temporal();
-}
-
-
bool
str_to_datetime_with_warn(THD *thd, CHARSET_INFO *cs,
- const char *str, size_t length, MYSQL_TIME *l_time,
- date_mode_t flags)
+ const char *str, size_t length, MYSQL_TIME *to,
+ date_mode_t mode)
{
- MYSQL_TIME_STATUS status;
- return str_to_datetime_with_warn(thd, cs, str, length, l_time, flags, &status);
+ Temporal::Warn_push warn(thd, NullS, to, mode);
+ Temporal_hybrid *t= new(to) Temporal_hybrid(thd, &warn, str, length, cs, mode);
+ return !t->is_valid_temporal();
}
bool double_to_datetime_with_warn(THD *thd, double value, MYSQL_TIME *ltime,
date_mode_t fuzzydate, const char *field_name)
{
- const ErrConvDouble str(value);
- Temporal_hybrid *t= new (ltime) Temporal_hybrid(thd, Sec6(value), fuzzydate,
- &str, field_name);
+ Temporal::Warn_push warn(thd, field_name, ltime, fuzzydate);
+ Temporal_hybrid *t= new (ltime) Temporal_hybrid(thd, &warn, value, fuzzydate);
return !t->is_valid_temporal();
}
@@ -460,9 +443,8 @@ bool decimal_to_datetime_with_warn(THD *thd, const my_decimal *value,
MYSQL_TIME *ltime,
date_mode_t fuzzydate, const char *field_name)
{
- const ErrConvDecimal str(value);
- Temporal_hybrid *t= new (ltime) Temporal_hybrid(thd, Sec6(value), fuzzydate,
- &str, field_name);
+ Temporal::Warn_push warn(thd, field_name, ltime, fuzzydate);
+ Temporal_hybrid *t= new (ltime) Temporal_hybrid(thd, &warn, value, fuzzydate);
return !t->is_valid_temporal();
}
@@ -471,14 +453,12 @@ bool int_to_datetime_with_warn(THD *thd, const Longlong_hybrid &nr,
MYSQL_TIME *ltime,
date_mode_t fuzzydate, const char *field_name)
{
- const ErrConvInteger str(nr);
/*
Note: conversion from an integer to TIME can overflow to '838:59:59.999999',
so the conversion result can have fractional digits.
*/
- Temporal_hybrid *t= new (ltime)
- Temporal_hybrid(thd, Sec6(nr),
- fuzzydate, &str, field_name);
+ Temporal::Warn_push warn(thd, field_name, ltime, fuzzydate);
+ Temporal_hybrid *t= new (ltime) Temporal_hybrid(thd, &warn, nr, fuzzydate);
return !t->is_valid_temporal();
}
@@ -909,20 +889,7 @@ void make_truncated_value_warning(THD *thd,
timestamp_type time_type,
const char *field_name)
{
- const char *type_str;
-
- switch (time_type) {
- case MYSQL_TIMESTAMP_DATE:
- type_str= "date";
- break;
- case MYSQL_TIMESTAMP_TIME:
- type_str= "time";
- break;
- case MYSQL_TIMESTAMP_DATETIME: // FALLTHROUGH
- default:
- type_str= "datetime";
- break;
- }
+ const char *type_str= Temporal::type_name_by_timestamp_type(time_type);
return thd->push_warning_wrong_or_truncated_value(level,
time_type <= MYSQL_TIMESTAMP_ERROR,
type_str, sval->ptr(), field_name);
@@ -1400,11 +1367,3 @@ void unpack_time(longlong packed, MYSQL_TIME *my_time,
break;
}
}
-
-
-bool my_decimal::to_datetime_with_warn(THD *thd, MYSQL_TIME *to,
- date_mode_t fuzzydate,
- const char *field_name)
-{
- return decimal_to_datetime_with_warn(thd, this, to, fuzzydate, field_name);
-}
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index 23fa678e7cf..a432f37b580 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -160,15 +160,6 @@ date_mode_t Temporal::sql_mode_for_dates(THD *thd)
}
-bool Dec_ptr::to_datetime_with_warn(THD *thd, MYSQL_TIME *to,
- date_mode_t fuzzydate, Item *item)
-{
- if (to_datetime_with_warn(thd, to, fuzzydate, item->field_name_or_null()))
- return item->null_value|= item->make_zero_date(to, fuzzydate);
- return item->null_value= false;
-}
-
-
my_decimal *Temporal::to_decimal(my_decimal *to) const
{
return date2my_decimal(this, to);
@@ -182,6 +173,20 @@ my_decimal *Temporal::bad_to_decimal(my_decimal *to) const
}
+void Temporal::make_from_str(THD *thd, Warn *warn,
+ const char *str, size_t length,
+ CHARSET_INFO *cs, date_mode_t fuzzydate)
+{
+ DBUG_EXECUTE_IF("str_to_datetime_warn",
+ push_warning(thd, Sql_condition::WARN_LEVEL_NOTE,
+ ER_YES, ErrConvString(str, length,cs).ptr()););
+ if (str_to_datetime(warn, str, length, cs, fuzzydate))
+ make_fuzzy_date(&warn->warnings, fuzzydate);
+ if (warn->warnings)
+ warn->set_str(str, length, &my_charset_bin);
+}
+
+
Temporal_hybrid::Temporal_hybrid(THD *thd, Item *item, date_mode_t fuzzydate)
{
if (item->get_date(thd, this, fuzzydate))
@@ -221,31 +226,30 @@ void Sec6::make_truncated_warning(THD *thd, const char *type_str) const
}
-bool Sec6::convert_to_mysql_time(THD *thd, MYSQL_TIME *ltime,
- date_mode_t fuzzydate, const ErrConv *str,
- const char *field_name) const
+bool Sec6::convert_to_mysql_time(THD *thd, int *warn, MYSQL_TIME *ltime,
+ date_mode_t fuzzydate) const
{
- int warn;
bool is_time= bool(fuzzydate & TIME_TIME_ONLY);
- const char *typestr= is_time ? "time" : "datetime";
- bool rc= is_time ? to_time(ltime, &warn) :
- to_datetime(ltime, fuzzydate, &warn);
+ bool rc= is_time ? to_time(ltime, warn) : to_datetime(ltime, fuzzydate, warn);
+ DBUG_ASSERT(*warn || !rc);
if (truncated())
- {
- // The value was already truncated at the constructor call time
- thd->push_warning_wrong_or_truncated_value(Sql_condition::WARN_LEVEL_WARN,
- !is_time, typestr,
- str->ptr(), field_name);
- }
- else if (rc || MYSQL_TIME_WARN_HAVE_WARNINGS(warn))
+ *warn|= MYSQL_TIME_WARN_TRUNCATED;
+ return rc;
+}
+
+
+void Temporal::push_conversion_warnings(THD *thd, bool totally_useless_value, int warn,
+ const char *typestr,
+ const char *field_name,
+ const char *value)
+{
+ if (MYSQL_TIME_WARN_HAVE_WARNINGS(warn))
thd->push_warning_wrong_or_truncated_value(Sql_condition::WARN_LEVEL_WARN,
- rc, typestr, str->ptr(),
- field_name);
+ totally_useless_value,
+ typestr, value, field_name);
else if (MYSQL_TIME_WARN_HAVE_NOTES(warn))
thd->push_warning_wrong_or_truncated_value(Sql_condition::WARN_LEVEL_NOTE,
- rc, typestr, str->ptr(),
- field_name);
- return rc;
+ false, typestr, value, field_name);
}
@@ -340,11 +344,10 @@ const LEX_CSTRING Interval_DDhhmmssff::m_type_name=
{STRING_WITH_LEN("INTERVAL DAY TO SECOND")};
-Interval_DDhhmmssff::Interval_DDhhmmssff(THD *thd, MYSQL_TIME_STATUS *st,
+Interval_DDhhmmssff::Interval_DDhhmmssff(THD *thd, Status *st,
bool push_warnings,
Item *item, ulong max_hour)
{
- my_time_status_init(st);
switch (item->cmp_type()) {
case ROW_RESULT:
DBUG_ASSERT(0);
@@ -425,7 +428,6 @@ Interval_DDhhmmssff::push_warning_wrong_or_truncated_value(THD *thd,
uint Interval_DDhhmmssff::fsp(THD *thd, Item *item)
{
- MYSQL_TIME_STATUS st;
switch (item->cmp_type()) {
case INT_RESULT:
case TIME_RESULT:
@@ -441,6 +443,7 @@ uint Interval_DDhhmmssff::fsp(THD *thd, Item *item)
}
if (!item->const_item() || item->is_expensive())
return TIME_SECOND_PART_DIGITS;
+ Status st;
Interval_DDhhmmssff it(thd, &st, false/*no warnings*/, item, UINT_MAX32);
return it.is_valid_interval_DDhhmmssff() ? st.precision :
TIME_SECOND_PART_DIGITS;
@@ -3995,47 +3998,87 @@ bool Type_handler_string_result::Item_val_bool(Item *item) const
/*************************************************************************/
-bool Type_handler_int_result::Item_get_date(THD *thd, Item *item,
- MYSQL_TIME *ltime,
- date_mode_t fuzzydate) const
+
+bool Type_handler::Item_get_date_with_warn(THD *thd, Item *item,
+ MYSQL_TIME *ltime,
+ date_mode_t fuzzydate) const
{
- return item->get_date_from_int(thd, ltime, fuzzydate);
+ Temporal::Warn_push warn(thd, item->field_name_or_null(), ltime, fuzzydate);
+ Item_get_date(thd, item, &warn, ltime, fuzzydate);
+ return ltime->time_type < 0;
}
-bool Type_handler_year::Item_get_date(THD *thd, Item *item, MYSQL_TIME *ltime,
+bool Type_handler::Item_func_hybrid_field_type_get_date_with_warn(THD *thd,
+ Item_func_hybrid_field_type *item,
+ MYSQL_TIME *ltime,
+ date_mode_t mode) const
+{
+ Temporal::Warn_push warn(thd, item->field_name_or_null(), ltime, mode);
+ Item_func_hybrid_field_type_get_date(thd, item, &warn, ltime, mode);
+ return ltime->time_type < 0;
+}
+
+
+/************************************************************************/
+void Type_handler_decimal_result::Item_get_date(THD *thd, Item *item,
+ Temporal::Warn *warn,
+ MYSQL_TIME *ltime,
+ date_mode_t fuzzydate) const
+{
+ new(ltime) Temporal_hybrid(thd, warn, VDec(item).ptr(), fuzzydate);
+}
+
+
+void Type_handler_int_result::Item_get_date(THD *thd, Item *item,
+ Temporal::Warn *warn,
+ MYSQL_TIME *to,
+ date_mode_t mode) const
+{
+ new(to) Temporal_hybrid(thd, warn, item->to_longlong_hybrid_null(), mode);
+}
+
+
+void Type_handler_year::Item_get_date(THD *thd, Item *item,
+ Temporal::Warn *warn,
+ MYSQL_TIME *ltime,
date_mode_t fuzzydate) const
{
- return item->null_value=
- VYear(item).to_mysql_time_with_warn(thd, ltime, fuzzydate,
- item->field_name_or_null());
+ VYear year(item);
+ DBUG_ASSERT(!year.truncated());
+ Longlong_hybrid_null nr(Longlong_null(year.to_YYYYMMDD(), year.is_null()),
+ item->unsigned_flag);
+ new(ltime) Temporal_hybrid(thd, warn, nr, fuzzydate);
}
-bool Type_handler_real_result::Item_get_date(THD *thd, Item *item,
+void Type_handler_real_result::Item_get_date(THD *thd, Item *item,
+ Temporal::Warn *warn,
MYSQL_TIME *ltime,
date_mode_t fuzzydate) const
{
- return item->get_date_from_real(thd, ltime, fuzzydate);
+ new(ltime) Temporal_hybrid(thd, warn, item->to_double_null(), fuzzydate);
}
-bool Type_handler_string_result::Item_get_date(THD *thd, Item *item,
+void Type_handler_string_result::Item_get_date(THD *thd, Item *item,
+ Temporal::Warn *warn,
MYSQL_TIME *ltime,
- date_mode_t fuzzydate) const
+ date_mode_t mode) const
{
- return item->get_date_from_string(thd, ltime, fuzzydate);
+ StringBuffer<40> tmp;
+ new(ltime) Temporal_hybrid(thd, warn, item->val_str(&tmp), mode);
}
-bool Type_handler_temporal_result::Item_get_date(THD *thd, Item *item,
+void Type_handler_temporal_result::Item_get_date(THD *thd, Item *item,
+ Temporal::Warn *warn,
MYSQL_TIME *ltime,
date_mode_t fuzzydate) const
{
DBUG_ASSERT(0); // Temporal type items must implement native get_date()
item->null_value= true;
- set_zero_time(ltime, mysql_timestamp_type());
- return true;
+ set_zero_time(ltime, MYSQL_TIMESTAMP_NONE);
}
@@ -4176,26 +4219,31 @@ Type_handler_decimal_result::Item_func_hybrid_field_type_val_decimal(
}
-bool
+void
Type_handler_decimal_result::Item_func_hybrid_field_type_get_date(
THD *thd,
Item_func_hybrid_field_type *item,
+ Temporal::Warn *warn,
MYSQL_TIME *ltime,
date_mode_t fuzzydate) const
{
- return VDec_op(item).to_datetime_with_warn(thd, ltime, fuzzydate, item);
+ new (ltime) Temporal_hybrid(thd, warn, VDec_op(item).ptr(), fuzzydate);
}
-bool
+void
Type_handler_year::Item_func_hybrid_field_type_get_date(
THD *thd,
Item_func_hybrid_field_type *item,
+ Temporal::Warn *warn,
MYSQL_TIME *ltime,
date_mode_t fuzzydate) const
{
- return item->null_value=
- VYear_op(item).to_mysql_time_with_warn(thd, ltime, fuzzydate, NULL);
+ VYear_op year(item);
+ DBUG_ASSERT(!year.truncated());
+ Longlong_hybrid_null nr(Longlong_null(year.to_YYYYMMDD(), year.is_null()),
+ item->unsigned_flag);
+ new(ltime) Temporal_hybrid(thd, warn, nr, fuzzydate);
}
@@ -4238,18 +4286,18 @@ Type_handler_int_result::Item_func_hybrid_field_type_val_decimal(
}
-bool
+void
Type_handler_int_result::Item_func_hybrid_field_type_get_date(
THD *thd,
Item_func_hybrid_field_type *item,
- MYSQL_TIME *ltime,
- date_mode_t fuzzydate) const
+ Temporal::Warn *warn,
+ MYSQL_TIME *to,
+ date_mode_t mode) const
{
- return item->get_date_from_int_op(thd, ltime, fuzzydate);
+ new(to) Temporal_hybrid(thd, warn, item->to_longlong_hybrid_null_op(), mode);
}
-
/***************************************************************************/
String *
@@ -4288,14 +4336,15 @@ Type_handler_real_result::Item_func_hybrid_field_type_val_decimal(
}
-bool
+void
Type_handler_real_result::Item_func_hybrid_field_type_get_date(
THD *thd,
Item_func_hybrid_field_type *item,
- MYSQL_TIME *ltime,
- date_mode_t fuzzydate) const
+ Temporal::Warn *warn,
+ MYSQL_TIME *to,
+ date_mode_t mode) const
{
- return item->get_date_from_real_op(thd, ltime, fuzzydate);
+ new(to) Temporal_hybrid(thd, warn, item->to_double_null_op(), mode);
}
@@ -4337,14 +4386,16 @@ Type_handler_temporal_result::Item_func_hybrid_field_type_val_decimal(
}
-bool
+void
Type_handler_temporal_result::Item_func_hybrid_field_type_get_date(
THD *thd,
Item_func_hybrid_field_type *item,
+ Temporal::Warn *warn,
MYSQL_TIME *ltime,
date_mode_t fuzzydate) const
{
- return item->date_op(thd, ltime, fuzzydate);
+ if (item->date_op(thd, ltime, fuzzydate))
+ set_zero_time(ltime, MYSQL_TIMESTAMP_NONE);
}
@@ -4386,14 +4437,16 @@ Type_handler_time_common::Item_func_hybrid_field_type_val_decimal(
}
-bool
+void
Type_handler_time_common::Item_func_hybrid_field_type_get_date(
THD *thd,
Item_func_hybrid_field_type *item,
+ Temporal::Warn *warn,
MYSQL_TIME *ltime,
date_mode_t fuzzydate) const
{
- return item->time_op(thd, ltime);
+ if (item->time_op(thd, ltime))
+ set_zero_time(ltime, MYSQL_TIMESTAMP_NONE);
}
@@ -4435,14 +4488,18 @@ Type_handler_string_result::Item_func_hybrid_field_type_val_decimal(
}
-bool
+void
Type_handler_string_result::Item_func_hybrid_field_type_get_date(
THD *thd,
Item_func_hybrid_field_type *item,
+ Temporal::Warn *warn,
MYSQL_TIME *ltime,
- date_mode_t fuzzydate) const
+ date_mode_t mode) const
{
- return item->get_date_from_str_op(thd, ltime, fuzzydate);
+ StringBuffer<40> tmp;
+ String *res= item->str_op(&tmp);
+ DBUG_ASSERT((res == NULL) == item->null_value);
+ new(ltime) Temporal_hybrid(thd, warn, res, mode);
}
/***************************************************************************/
@@ -4907,7 +4964,7 @@ bool Type_handler_numeric::
Item_func_min_max_get_date(THD *thd, Item_func_min_max *func,
MYSQL_TIME *ltime, date_mode_t fuzzydate) const
{
- return Item_get_date(thd, func, ltime, fuzzydate);
+ return Item_get_date_with_warn(thd, func, ltime, fuzzydate);
}
@@ -7508,9 +7565,9 @@ Type_handler_date_common::create_literal_item(THD *thd,
CHARSET_INFO *cs,
bool send_error) const
{
- MYSQL_TIME_STATUS st;
+ Temporal::Warn st;
Item_literal *item= NULL;
- Temporal_hybrid tmp(&st, str, length, cs, sql_mode_for_dates(thd));
+ Temporal_hybrid tmp(thd, &st, str, length, cs, sql_mode_for_dates(thd));
if (tmp.is_valid_temporal() &&
tmp.get_mysql_time()->time_type == MYSQL_TIMESTAMP_DATE &&
!have_important_literal_warnings(&st))
@@ -7528,9 +7585,9 @@ Type_handler_temporal_with_date::create_literal_item(THD *thd,
CHARSET_INFO *cs,
bool send_error) const
{
- MYSQL_TIME_STATUS st;
+ Temporal::Warn st;
Item_literal *item= NULL;
- Temporal_hybrid tmp(&st, str, length, cs, sql_mode_for_dates(thd));
+ Temporal_hybrid tmp(thd, &st, str, length, cs, sql_mode_for_dates(thd));
if (tmp.is_valid_temporal() &&
tmp.get_mysql_time()->time_type == MYSQL_TIMESTAMP_DATETIME &&
!have_important_literal_warnings(&st))
diff --git a/sql/sql_type.h b/sql/sql_type.h
index 45c98f7b7d3..5de4c8e431a 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -96,6 +96,7 @@ protected:
my_decimal *m_ptr;
Dec_ptr() { }
public:
+ Dec_ptr(my_decimal *ptr) :m_ptr(ptr) { }
bool is_null() const { return m_ptr == NULL; }
const my_decimal *ptr() const { return m_ptr; }
const my_decimal *ptr_or(const my_decimal *def) const
@@ -113,14 +114,6 @@ public:
longlong to_longlong(bool unsigned_flag)
{ return m_ptr ? m_ptr->to_longlong(unsigned_flag) : 0; }
bool to_bool() const { return m_ptr ? m_ptr->to_bool() : false; }
- bool to_datetime_with_warn(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate,
- const char *field_name)
- {
- return m_ptr ? m_ptr->to_datetime_with_warn(thd, to, fuzzydate, field_name) :
- true;
- }
- bool to_datetime_with_warn(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate,
- Item *item);
String *to_string(String *to) const
{
return m_ptr ? m_ptr->to_string(to) : NULL;
@@ -260,20 +253,23 @@ public:
long usec() const { return m_usec; }
/**
Converts Sec6 to MYSQL_TIME
-
- @param ltime converted value will be written here
+ @param thd current thd
+ @param [out] warn conversion warnings will be written here
+ @param [out] ltime converted value will be written here
@param fuzzydate conversion flags (TIME_INVALID_DATE, etc)
- @param str original number, as an ErrConv. For the warning
- @param field_name field name or NULL if not a field. For the warning
@returns false for success, true for a failure
*/
- bool convert_to_mysql_time(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate,
- const ErrConv *str, const char *field_name) const;
+ bool convert_to_mysql_time(THD *thd,
+ int *warn,
+ MYSQL_TIME *ltime,
+ date_mode_t fuzzydate) const;
// Convert a number in format hhhmmss.ff to TIME'hhh:mm:ss.ff'
bool to_time(MYSQL_TIME *to, int *warn) const
{
- return number_to_time(m_neg, m_sec, m_usec, to, warn);
+ bool rc= number_to_time(m_neg, m_sec, m_usec, to, warn);
+ DBUG_ASSERT(*warn || !rc);
+ return rc;
}
/*
Convert a number in format YYYYMMDDhhmmss.ff to
@@ -286,9 +282,11 @@ public:
*warn= MYSQL_TIME_WARN_OUT_OF_RANGE;
return true;
}
- return number_to_datetime(m_sec, m_usec, to,
- ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE),
- warn) == -1;
+ bool rc= number_to_datetime(m_sec, m_usec, to,
+ ulonglong(flags & TIME_MODE_FOR_XXX_TO_DATE),
+ warn) == -1;
+ DBUG_ASSERT(*warn || !rc);
+ return rc;
}
// Convert elapsed seconds to TIME
bool sec_to_time(MYSQL_TIME *ltime, uint dec) const
@@ -394,20 +392,12 @@ class Year
protected:
uint m_year;
bool m_truncated;
- bool to_mysql_time_with_warn(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate,
- const char *field_name) const
- {
- // Make it YYYYMMDD
- Longlong_hybrid value(static_cast<ulonglong>(m_year) * 10000, true);
- const ErrConvInteger str(value);
- Sec6 sec(value);
- return sec.convert_to_mysql_time(thd, to, fuzzydate, &str, field_name);
- }
uint year_precision(const Item *item) const;
public:
Year(): m_year(0), m_truncated(false) { }
Year(longlong value, bool unsigned_flag, uint length);
uint year() const { return m_year; }
+ uint to_YYYYMMDD() const { return m_year * 10000; }
bool truncated() const { return m_truncated; }
};
@@ -419,12 +409,6 @@ public:
:Year(nr.is_null() ? 0 : nr.value(), unsigned_flag, length),
Null_flag(nr.is_null())
{ }
- bool to_mysql_time_with_warn(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate,
- const char *field_name) const
- {
- return m_is_null ? true :
- Year::to_mysql_time_with_warn(thd, to, fuzzydate, field_name);
- }
};
@@ -442,15 +426,109 @@ public:
};
+class Double_null: public Null_flag
+{
+protected:
+ double m_value;
+public:
+ Double_null(double value, bool is_null)
+ :Null_flag(is_null), m_value(value)
+ { }
+ double value() const { return m_value; }
+};
+
+
class Temporal: protected MYSQL_TIME
{
public:
+ class Status: public MYSQL_TIME_STATUS
+ {
+ public:
+ Status() { my_time_status_init(this); }
+ };
+
+ class Warn: public ErrBuff,
+ public Status
+ {
+ public:
+ void push_conversion_warnings(THD *thd, bool totally_useless_value, date_mode_t mode,
+ timestamp_type tstype, const char *name)
+ {
+ const char *typestr= tstype >= 0 ? type_name_by_timestamp_type(tstype) :
+ mode & TIME_TIME_ONLY ? "time" : "datetime";
+ Temporal::push_conversion_warnings(thd, totally_useless_value, warnings, typestr,
+ name, ptr());
+ }
+ };
+
+ class Warn_push: public Warn
+ {
+ THD *m_thd;
+ const char *m_name;
+ const MYSQL_TIME *m_ltime;
+ date_mode_t m_mode;
+ public:
+ Warn_push(THD *thd, const char *name,
+ const MYSQL_TIME *ltime, date_mode_t mode)
+ :m_thd(thd), m_name(name), m_ltime(ltime), m_mode(mode)
+ { }
+ ~Warn_push()
+ {
+ if (warnings)
+ push_conversion_warnings(m_thd, m_ltime->time_type < 0,
+ m_mode, m_ltime->time_type, m_name);
+ }
+ };
+
+public:
static date_mode_t sql_mode_for_dates(THD *thd);
bool is_valid_temporal() const
{
DBUG_ASSERT(time_type != MYSQL_TIMESTAMP_ERROR);
return time_type != MYSQL_TIMESTAMP_NONE;
}
+ static const char *type_name_by_timestamp_type(timestamp_type time_type)
+ {
+ switch (time_type) {
+ case MYSQL_TIMESTAMP_DATE: return "date";
+ case MYSQL_TIMESTAMP_TIME: return "time";
+ case MYSQL_TIMESTAMP_DATETIME: // FALLTHROUGH
+ default:
+ break;
+ }
+ return "datetime";
+ }
+ static void push_conversion_warnings(THD *thd, bool totally_useless_value, int warn,
+ const char *type_name,
+ const char *field_name,
+ const char *value);
+ /*
+ This method is used if the item was not null but convertion to
+ TIME/DATE/DATETIME failed. We return a zero date if allowed,
+ otherwise - null.
+ */
+ void make_fuzzy_date(int *warn, date_mode_t fuzzydate)
+ {
+ /*
+ In the following scenario:
+ - The caller expected to get a TIME value
+ - Item returned a not NULL string or numeric value
+ - But then conversion from string or number to TIME failed
+ we need to change the default time_type from MYSQL_TIMESTAMP_DATE
+ (which was set in bzero) to MYSQL_TIMESTAMP_TIME and therefore
+ return TIME'00:00:00' rather than DATE'0000-00-00'.
+ If we don't do this, methods like Item::get_time_with_conversion()
+ will erroneously subtract CURRENT_DATE from '0000-00-00 00:00:00'
+ and return TIME'-838:59:59' instead of TIME'00:00:00' as a result.
+ */
+ timestamp_type tstype= !(fuzzydate & TIME_FUZZY_DATES) ?
+ MYSQL_TIMESTAMP_NONE :
+ fuzzydate & TIME_TIME_ONLY ?
+ MYSQL_TIMESTAMP_TIME :
+ MYSQL_TIMESTAMP_DATETIME;
+ set_zero_time(this, tstype);
+ }
+
protected:
my_decimal *bad_to_decimal(my_decimal *to) const;
my_decimal *to_decimal(my_decimal *to) const;
@@ -465,6 +543,39 @@ protected:
*warn= MYSQL_TIME_WARN_OUT_OF_RANGE;
time_type= MYSQL_TIMESTAMP_NONE;
}
+ void make_from_sec6(THD *thd, MYSQL_TIME_STATUS *st,
+ const Sec6 &nr, date_mode_t mode)
+ {
+ if (nr.convert_to_mysql_time(thd, &st->warnings, this, mode))
+ make_fuzzy_date(&st->warnings, mode);
+ }
+ void make_from_str(THD *thd, Warn *warn,
+ const char *str, size_t length, CHARSET_INFO *cs,
+ date_mode_t fuzzydate);
+ void make_from_double(THD *thd, Warn *warn, double nr, date_mode_t mode)
+ {
+ make_from_sec6(thd, warn, Sec6(nr), mode);
+ if (warn->warnings)
+ warn->set_double(nr);
+ }
+ void make_from_longlong_hybrid(THD *thd, Warn *warn,
+ const Longlong_hybrid &nr, date_mode_t mode)
+ {
+ /*
+ Note: conversion from an integer to TIME can overflow to
+ '838:59:59.999999', so the conversion result can have fractional digits.
+ */
+ make_from_sec6(thd, warn, Sec6(nr), mode);
+ if (warn->warnings)
+ warn->set_longlong(nr);
+ }
+ void make_from_decimal(THD *thd, Warn *warn,
+ const my_decimal *nr, date_mode_t mode)
+ {
+ make_from_sec6(thd, warn, Sec6(nr), mode);
+ if (warn->warnings)
+ warn->set_decimal(nr);
+ }
bool str_to_time(MYSQL_TIME_STATUS *st, const char *str, size_t length,
CHARSET_INFO *cs, date_mode_t fuzzydate);
bool str_to_datetime(MYSQL_TIME_STATUS *st, const char *str, size_t length,
@@ -506,6 +617,7 @@ public:
class Temporal_hybrid: public Temporal
{
public:
+ // Contructors for Item
Temporal_hybrid(THD *thd, Item *item, date_mode_t fuzzydate);
Temporal_hybrid(THD *thd, Item *item)
:Temporal_hybrid(thd, item, sql_mode_for_dates(thd))
@@ -513,18 +625,56 @@ public:
Temporal_hybrid(Item *item)
:Temporal_hybrid(current_thd, item)
{ }
- Temporal_hybrid(MYSQL_TIME_STATUS *st, const char *str, size_t length,
- CHARSET_INFO *cs, date_mode_t fuzzydate)
+
+ // Constructors for non-NULL values
+ Temporal_hybrid(THD *thd, Warn *warn,
+ const char *str, size_t length, CHARSET_INFO *cs,
+ date_mode_t fuzzydate)
+ {
+ make_from_str(thd, warn, str, length, cs, fuzzydate);
+ }
+ Temporal_hybrid(THD *thd, Warn *warn,
+ const Longlong_hybrid &nr, date_mode_t fuzzydate)
+ {
+ make_from_longlong_hybrid(thd, warn, nr, fuzzydate);
+ }
+ Temporal_hybrid(THD *thd, Warn *warn, double nr, date_mode_t fuzzydate)
{
- if (str_to_datetime(st, str, length, cs, fuzzydate))
+ make_from_double(thd, warn, nr, fuzzydate);
+ }
+
+ // Constructors for nullable values
+ Temporal_hybrid(THD *thd, Warn *warn, const String *str, date_mode_t mode)
+ {
+ if (!str)
+ time_type= MYSQL_TIMESTAMP_NONE;
+ else
+ make_from_str(thd, warn, str->ptr(), str->length(), str->charset(), mode);
+ }
+ Temporal_hybrid(THD *thd, Warn *warn,
+ const Longlong_hybrid_null &nr, date_mode_t fuzzydate)
+ {
+ if (nr.is_null())
time_type= MYSQL_TIMESTAMP_NONE;
+ else
+ make_from_longlong_hybrid(thd, warn, nr, fuzzydate);
}
- Temporal_hybrid(THD *thd, const Sec6 &sec, date_mode_t fuzzydate,
- const ErrConv *str, const char *field_name)
+ Temporal_hybrid(THD *thd, Warn *warn, const Double_null &nr, date_mode_t mode)
{
- if (sec.convert_to_mysql_time(thd, this, fuzzydate, str, field_name))
+ if (nr.is_null())
time_type= MYSQL_TIMESTAMP_NONE;
+ else
+ make_from_double(thd, warn, nr.value(), mode);
}
+ Temporal_hybrid(THD *thd, Warn *warn, const my_decimal *nr, date_mode_t mode)
+ {
+ if (!nr)
+ time_type= MYSQL_TIMESTAMP_NONE;
+ else
+ make_from_decimal(thd, warn, nr, mode);
+ }
+ // End of constuctors
+
longlong to_longlong() const
{
if (!is_valid_temporal())
@@ -705,11 +855,11 @@ public:
return 87649415;
}
public:
- Interval_DDhhmmssff(THD *thd, MYSQL_TIME_STATUS *st, bool push_warnings,
+ Interval_DDhhmmssff(THD *thd, Status *st, bool push_warnings,
Item *item, ulong max_hour);
Interval_DDhhmmssff(THD *thd, Item *item)
{
- MYSQL_TIME_STATUS st;
+ Status st;
new(this) Interval_DDhhmmssff(thd, &st, true, item, max_useful_hour());
}
const MYSQL_TIME *get_mysql_time() const
@@ -2549,8 +2699,11 @@ public:
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const= 0;
virtual bool Item_val_bool(Item *item) const= 0;
- virtual bool Item_get_date(THD *thd, Item *item, MYSQL_TIME *ltime,
+ virtual void Item_get_date(THD *thd, Item *item,
+ Temporal::Warn *buff, MYSQL_TIME *ltime,
date_mode_t fuzzydate) const= 0;
+ bool Item_get_date_with_warn(THD *thd, Item *item, MYSQL_TIME *ltime,
+ date_mode_t fuzzydate) const;
virtual longlong Item_val_int_signed_typecast(Item *item) const= 0;
virtual longlong Item_val_int_unsigned_typecast(Item *item) const= 0;
@@ -2571,10 +2724,15 @@ public:
Item_func_hybrid_field_type *,
my_decimal *) const= 0;
virtual
- bool Item_func_hybrid_field_type_get_date(THD *,
+ void Item_func_hybrid_field_type_get_date(THD *,
Item_func_hybrid_field_type *,
+ Temporal::Warn *,
MYSQL_TIME *,
date_mode_t fuzzydate) const= 0;
+ bool Item_func_hybrid_field_type_get_date_with_warn(THD *thd,
+ Item_func_hybrid_field_type *,
+ MYSQL_TIME *,
+ date_mode_t) const;
virtual
String *Item_func_min_max_val_str(Item_func_min_max *, String *) const= 0;
virtual
@@ -2836,11 +2994,12 @@ public:
DBUG_ASSERT(0);
return false;
}
- bool Item_get_date(THD *thd, Item *item,
- MYSQL_TIME *ltime, date_mode_t fuzzydate) const
+ void Item_get_date(THD *thd, Item *item,
+ Temporal::Warn *warn, MYSQL_TIME *ltime,
+ date_mode_t fuzzydate) const
{
DBUG_ASSERT(0);
- return true;
+ set_zero_time(ltime, MYSQL_TIMESTAMP_NONE);
}
longlong Item_val_int_signed_typecast(Item *item) const
{
@@ -2882,13 +3041,14 @@ public:
DBUG_ASSERT(0);
return NULL;
}
- bool Item_func_hybrid_field_type_get_date(THD *,
+ void Item_func_hybrid_field_type_get_date(THD *,
Item_func_hybrid_field_type *,
- MYSQL_TIME *,
+ Temporal::Warn *,
+ MYSQL_TIME *ltime,
date_mode_t fuzzydate) const
{
DBUG_ASSERT(0);
- return true;
+ set_zero_time(ltime, MYSQL_TIMESTAMP_NONE);
}
String *Item_func_min_max_val_str(Item_func_min_max *, String *) const
@@ -3058,8 +3218,8 @@ public:
bool Item_func_signed_fix_length_and_dec(Item_func_signed *item) const;
bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const;
bool Item_val_bool(Item *item) const;
- bool Item_get_date(THD *thd, Item *item, MYSQL_TIME *ltime,
- date_mode_t fuzzydate) const;
+ void Item_get_date(THD *thd, Item *item, Temporal::Warn *warn,
+ MYSQL_TIME *ltime, date_mode_t fuzzydate) const;
longlong Item_val_int_signed_typecast(Item *item) const;
longlong Item_val_int_unsigned_typecast(Item *item) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
@@ -3072,8 +3232,9 @@ public:
my_decimal *Item_func_hybrid_field_type_val_decimal(
Item_func_hybrid_field_type *,
my_decimal *) const;
- bool Item_func_hybrid_field_type_get_date(THD *,
+ void Item_func_hybrid_field_type_get_date(THD *,
Item_func_hybrid_field_type *,
+ Temporal::Warn *,
MYSQL_TIME *,
date_mode_t fuzzydate) const;
String *Item_func_min_max_val_str(Item_func_min_max *, String *) const;
@@ -3156,11 +3317,8 @@ public:
{
return VDec(item).to_bool();
}
- bool Item_get_date(THD *thd, Item *item, MYSQL_TIME *ltime,
- date_mode_t fuzzydate) const
- {
- return VDec(item).to_datetime_with_warn(thd, ltime, fuzzydate, item);
- }
+ void Item_get_date(THD *thd, Item *item, Temporal::Warn *warn,
+ MYSQL_TIME *ltime, date_mode_t fuzzydate) const;
longlong Item_val_int_signed_typecast(Item *item) const;
longlong Item_val_int_unsigned_typecast(Item *item) const
{
@@ -3176,8 +3334,9 @@ public:
my_decimal *Item_func_hybrid_field_type_val_decimal(
Item_func_hybrid_field_type *,
my_decimal *) const;
- bool Item_func_hybrid_field_type_get_date(THD *,
+ void Item_func_hybrid_field_type_get_date(THD *,
Item_func_hybrid_field_type *,
+ Temporal::Warn *,
MYSQL_TIME *,
date_mode_t fuzzydate) const;
String *Item_func_min_max_val_str(Item_func_min_max *, String *) const;
@@ -3366,8 +3525,8 @@ public:
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
bool Item_val_bool(Item *item) const;
- bool Item_get_date(THD *thd, Item *item, MYSQL_TIME *ltime,
- date_mode_t fuzzydate) const;
+ void Item_get_date(THD *thd, Item *item, Temporal::Warn *warn,
+ MYSQL_TIME *ltime, date_mode_t fuzzydate) const;
longlong Item_val_int_signed_typecast(Item *item) const;
longlong Item_val_int_unsigned_typecast(Item *item) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
@@ -3380,8 +3539,9 @@ public:
my_decimal *Item_func_hybrid_field_type_val_decimal(
Item_func_hybrid_field_type *,
my_decimal *) const;
- bool Item_func_hybrid_field_type_get_date(THD *,
+ void Item_func_hybrid_field_type_get_date(THD *,
Item_func_hybrid_field_type *,
+ Temporal::Warn *,
MYSQL_TIME *,
date_mode_t fuzzydate) const;
String *Item_func_min_max_val_str(Item_func_min_max *, String *) const;
@@ -3448,8 +3608,8 @@ public:
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
bool Item_val_bool(Item *item) const;
- bool Item_get_date(THD *thd, Item *item, MYSQL_TIME *ltime,
- date_mode_t fuzzydate) const;
+ void Item_get_date(THD *thd, Item *item, Temporal::Warn *warn,
+ MYSQL_TIME *ltime, date_mode_t fuzzydate) const;
longlong Item_val_int_signed_typecast(Item *item) const;
longlong Item_val_int_unsigned_typecast(Item *item) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
@@ -3462,8 +3622,9 @@ public:
my_decimal *Item_func_hybrid_field_type_val_decimal(
Item_func_hybrid_field_type *,
my_decimal *) const;
- bool Item_func_hybrid_field_type_get_date(THD *,
+ void Item_func_hybrid_field_type_get_date(THD *,
Item_func_hybrid_field_type *,
+ Temporal::Warn *,
MYSQL_TIME *,
date_mode_t fuzzydate) const;
bool Item_func_min_max_get_date(THD *thd, Item_func_min_max*,
@@ -3565,8 +3726,8 @@ public:
bool Item_func_signed_fix_length_and_dec(Item_func_signed *item) const;
bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const;
bool Item_val_bool(Item *item) const;
- bool Item_get_date(THD *thd, Item *item, MYSQL_TIME *ltime,
- date_mode_t fuzzydate) const;
+ void Item_get_date(THD *thd, Item *item, Temporal::Warn *warn,
+ MYSQL_TIME *ltime, date_mode_t fuzzydate) const;
longlong Item_val_int_signed_typecast(Item *item) const;
longlong Item_val_int_unsigned_typecast(Item *item) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
@@ -3579,8 +3740,9 @@ public:
my_decimal *Item_func_hybrid_field_type_val_decimal(
Item_func_hybrid_field_type *,
my_decimal *) const;
- bool Item_func_hybrid_field_type_get_date(THD *,
+ void Item_func_hybrid_field_type_get_date(THD *,
Item_func_hybrid_field_type *,
+ Temporal::Warn *,
MYSQL_TIME *,
date_mode_t fuzzydate) const;
String *Item_func_min_max_val_str(Item_func_min_max *, String *) const;
@@ -3901,10 +4063,11 @@ public:
const Column_definition_attributes *attr,
uint32 flags) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
- bool Item_get_date(THD *thd, Item *item, MYSQL_TIME *ltime,
- date_mode_t fuzzydate) const;
- bool Item_func_hybrid_field_type_get_date(THD *,
+ void Item_get_date(THD *thd, Item *item, Temporal::Warn *warn,
+ MYSQL_TIME *ltime, date_mode_t fuzzydate) const;
+ void Item_func_hybrid_field_type_get_date(THD *,
Item_func_hybrid_field_type *item,
+ Temporal::Warn *,
MYSQL_TIME *to,
date_mode_t fuzzydate) const;
};
@@ -4088,8 +4251,9 @@ public:
my_decimal *Item_func_hybrid_field_type_val_decimal(
Item_func_hybrid_field_type *,
my_decimal *) const;
- bool Item_func_hybrid_field_type_get_date(THD *,
+ void Item_func_hybrid_field_type_get_date(THD *,
Item_func_hybrid_field_type *,
+ Temporal::Warn *,
MYSQL_TIME *,
date_mode_t fuzzydate) const;
String *Item_func_min_max_val_str(Item_func_min_max *, String *) const;
diff --git a/sql/sql_type_int.h b/sql/sql_type_int.h
index 6c88222fed0..1cc93415176 100644
--- a/sql/sql_type_int.h
+++ b/sql/sql_type_int.h
@@ -67,4 +67,16 @@ public:
}
};
+
+class Longlong_hybrid_null: public Longlong_hybrid,
+ public Null_flag
+{
+public:
+ Longlong_hybrid_null(const Longlong_null &nr, bool unsigned_flag)
+ :Longlong_hybrid(nr.value(), unsigned_flag),
+ Null_flag(nr.is_null())
+ { }
+};
+
+
#endif // SQL_TYPE_INT_INCLUDED