Commit c45050d2 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-16935 Change the parameter of Field_xxx::store_TIME_with_dec() to const...

MDEV-16935 Change the parameter of Field_xxx::store_TIME_with_dec() to const Datetime* and const Time*
parent 522cd3c7
...@@ -5020,13 +5020,12 @@ my_time_t Field_timestamp::get_timestamp(const uchar *pos, ...@@ -5020,13 +5020,12 @@ my_time_t Field_timestamp::get_timestamp(const uchar *pos,
} }
int Field_timestamp::store_TIME_with_warning(THD *thd, MYSQL_TIME *l_time, int Field_timestamp::store_TIME_with_warning(THD *thd, const Datetime *dt,
const ErrConv *str, int was_cut) const ErrConv *str, int was_cut)
{ {
ASSERT_COLUMN_MARKED_FOR_WRITE; ASSERT_COLUMN_MARKED_FOR_WRITE;
uint error = 0; uint error = 0;
if (MYSQL_TIME_WARN_HAVE_WARNINGS(was_cut) || !dt->is_valid_datetime())
if (MYSQL_TIME_WARN_HAVE_WARNINGS(was_cut) || !l_time)
{ {
error= 1; error= 1;
set_datetime_warning(WARN_DATA_TRUNCATED, set_datetime_warning(WARN_DATA_TRUNCATED,
...@@ -5038,10 +5037,12 @@ int Field_timestamp::store_TIME_with_warning(THD *thd, MYSQL_TIME *l_time, ...@@ -5038,10 +5037,12 @@ int Field_timestamp::store_TIME_with_warning(THD *thd, MYSQL_TIME *l_time,
set_datetime_warning(Sql_condition::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, set_datetime_warning(Sql_condition::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED,
str, MYSQL_TIMESTAMP_DATETIME, 1); str, MYSQL_TIMESTAMP_DATETIME, 1);
} }
/* Only convert a correct date (not a zero date) */ /* Only convert a correct date (not a zero date) */
if (l_time && l_time->month) if (dt->is_valid_datetime() && dt->get_mysql_time()->month)
{ {
uint conversion_error; uint conversion_error;
const MYSQL_TIME *l_time= dt->get_mysql_time();
my_time_t timestamp= TIME_to_timestamp(thd, l_time, &conversion_error); my_time_t timestamp= TIME_to_timestamp(thd, l_time, &conversion_error);
if (timestamp == 0 && l_time->second_part == 0) if (timestamp == 0 && l_time->second_part == 0)
conversion_error= ER_WARN_DATA_OUT_OF_RANGE; conversion_error= ER_WARN_DATA_OUT_OF_RANGE;
...@@ -5074,46 +5075,37 @@ int Field_timestamp::store_time_dec(const MYSQL_TIME *ltime, uint dec) ...@@ -5074,46 +5075,37 @@ int Field_timestamp::store_time_dec(const MYSQL_TIME *ltime, uint dec)
ErrConvTime str(ltime); ErrConvTime str(ltime);
THD *thd= get_thd(); THD *thd= get_thd();
Datetime dt(thd, &warn, ltime, sql_mode_for_timestamp(thd)); Datetime dt(thd, &warn, ltime, sql_mode_for_timestamp(thd));
ltime= dt.is_valid_datetime() ? dt.get_mysql_time() : NULL; return store_TIME_with_warning(thd, &dt, &str, warn);
return store_TIME_with_warning(thd, const_cast<MYSQL_TIME*>(ltime),
&str, warn);
} }
int Field_timestamp::store(const char *from,size_t len,CHARSET_INFO *cs) int Field_timestamp::store(const char *from,size_t len,CHARSET_INFO *cs)
{ {
MYSQL_TIME l_time;
MYSQL_TIME_STATUS status;
ErrConvString str(from, len, cs); ErrConvString str(from, len, cs);
THD *thd= get_thd(); THD *thd= get_thd();
bool rc= str_to_datetime(cs, from, len, &l_time, int error;
sql_mode_for_timestamp(thd), &status); Datetime dt(&error, from, len, cs, sql_mode_for_timestamp(thd));
return store_TIME_with_warning(thd, rc ? NULL : &l_time, &str, return store_TIME_with_warning(thd, &dt, &str, error);
status.warnings);
} }
int Field_timestamp::store(double nr) int Field_timestamp::store(double nr)
{ {
MYSQL_TIME l_time;
int error; int error;
ErrConvDouble str(nr); ErrConvDouble str(nr);
THD *thd= get_thd(); THD *thd= get_thd();
bool rc= Sec6(nr).to_datetime(&l_time, sql_mode_for_timestamp(thd), &error); Datetime dt(&error, nr, sql_mode_for_timestamp(thd));
return store_TIME_with_warning(thd, rc ? NULL : &l_time, &str, error); return store_TIME_with_warning(thd, &dt, &str, error);
} }
int Field_timestamp::store(longlong nr, bool unsigned_val) int Field_timestamp::store(longlong nr, bool unsigned_val)
{ {
MYSQL_TIME l_time;
int error; int error;
ErrConvInteger str(nr, unsigned_val); ErrConvInteger str(nr, unsigned_val);
THD *thd= get_thd(); THD *thd= get_thd();
bool rc= Sec6(nr, unsigned_val).to_datetime(&l_time, Datetime dt(&error, nr, sql_mode_for_timestamp(thd));
sql_mode_for_timestamp(thd), return store_TIME_with_warning(thd, &dt, &str, error);
&error);
return store_TIME_with_warning(thd, rc ? NULL : &l_time, &str, error);
} }
...@@ -5410,11 +5402,10 @@ my_decimal *Field_timestamp_with_dec::val_decimal(my_decimal *d) ...@@ -5410,11 +5402,10 @@ my_decimal *Field_timestamp_with_dec::val_decimal(my_decimal *d)
int Field_timestamp::store_decimal(const my_decimal *d) int Field_timestamp::store_decimal(const my_decimal *d)
{ {
int error; int error;
MYSQL_TIME ltime;
THD *thd= get_thd(); THD *thd= get_thd();
ErrConvDecimal str(d); ErrConvDecimal str(d);
bool rc= Sec6(d).to_datetime(&ltime, sql_mode_for_timestamp(thd), &error); Datetime dt(&error, d, sql_mode_for_timestamp(thd));
return store_TIME_with_warning(thd, rc ? NULL : &ltime, &str, error); return store_TIME_with_warning(thd, &dt, &str, error);
} }
int Field_timestamp_with_dec::set_time() int Field_timestamp_with_dec::set_time()
...@@ -5538,91 +5529,78 @@ void Field_temporal::set_warnings(Sql_condition::enum_warning_level trunc_level, ...@@ -5538,91 +5529,78 @@ void Field_temporal::set_warnings(Sql_condition::enum_warning_level trunc_level,
3 Datetime value that was cut (warning level NOTE) 3 Datetime value that was cut (warning level NOTE)
This is used by opt_range.cc:get_mm_leaf(). This is used by opt_range.cc:get_mm_leaf().
*/ */
int Field_temporal_with_date::store_TIME_with_warning(MYSQL_TIME *ltime, int Field_temporal_with_date::store_TIME_with_warning(const Datetime *dt,
const ErrConv *str, const ErrConv *str,
int was_cut) int was_cut)
{ {
Sql_condition::enum_warning_level trunc_level= Sql_condition::WARN_LEVEL_WARN; Sql_condition::enum_warning_level trunc_level= Sql_condition::WARN_LEVEL_WARN;
int ret; timestamp_type ts_type= type_handler()->mysql_timestamp_type();
ASSERT_COLUMN_MARKED_FOR_WRITE; ASSERT_COLUMN_MARKED_FOR_WRITE;
// Handle totally bad values
if (was_cut == 0 && !ltime) // special case: zero date if (!dt->is_valid_datetime())
{ {
was_cut= MYSQL_TIME_WARN_OUT_OF_RANGE; static const Datetime zero;
store_TIME(const_cast<MYSQL_TIME*>(Datetime().get_mysql_time())); store_TIME(zero.get_mysql_time());
ret= 2; if (was_cut == 0) // special case: zero date
{
set_warnings(trunc_level, str, MYSQL_TIME_WARN_OUT_OF_RANGE, ts_type);
return 2;
}
set_warnings(trunc_level, str, MYSQL_TIME_WARN_TRUNCATED, ts_type);
return 1;
} }
else if (!ltime) // Adjust and store the value
if (ts_type == MYSQL_TIMESTAMP_DATE)
{ {
was_cut= MYSQL_TIME_WARN_TRUNCATED; if (!dt->hhmmssff_is_zero())
store_TIME(const_cast<MYSQL_TIME*>(Datetime().get_mysql_time())); was_cut|= MYSQL_TIME_NOTE_TRUNCATED;
ret= 1; store_TIME(dt->get_mysql_time());
} }
else if (!MYSQL_TIME_WARN_HAVE_WARNINGS(was_cut) && else if (dt->fraction_remainder(decimals()))
(MYSQL_TIME_WARN_HAVE_NOTES(was_cut) ||
(type_handler()->mysql_timestamp_type() == MYSQL_TIMESTAMP_DATE &&
(ltime->hour || ltime->minute || ltime->second || ltime->second_part))))
{ {
trunc_level= Sql_condition::WARN_LEVEL_NOTE; Datetime truncated(dt->trunc(decimals()));
was_cut|= MYSQL_TIME_WARN_TRUNCATED; store_TIME(truncated.get_mysql_time());
store_TIME(ltime);
ret= 3;
} }
else else
{ store_TIME(dt->get_mysql_time());
store_TIME(ltime); // Caclulate return value and send warnings if needed
ret= was_cut ? 2 : 0; return store_TIME_return_code_with_warnings(was_cut, str, ts_type);
}
set_warnings(trunc_level, str, was_cut,
type_handler()->mysql_timestamp_type());
return ret;
} }
int Field_temporal_with_date::store(const char *from, size_t len, CHARSET_INFO *cs) int Field_temporal_with_date::store(const char *from, size_t len, CHARSET_INFO *cs)
{ {
MYSQL_TIME ltime; int error;
MYSQL_TIME_STATUS status;
THD *thd= get_thd();
ErrConvString str(from, len, cs); ErrConvString str(from, len, cs);
bool rc= str_to_datetime(cs, from, len, &ltime, sql_mode_for_dates(thd), Datetime dt(&error, from, len, cs, sql_mode_for_dates(get_thd()));
&status); return store_TIME_with_warning(&dt, &str, error);
return store_TIME_with_warning(rc ? NULL : &ltime, &str, status.warnings);
} }
int Field_temporal_with_date::store(double nr) int Field_temporal_with_date::store(double nr)
{ {
int error= 0; int error;
MYSQL_TIME ltime;
THD *thd= get_thd();
ErrConvDouble str(nr); ErrConvDouble str(nr);
bool rc= Sec6(nr).to_datetime(&ltime, sql_mode_for_dates(thd), &error); Datetime dt(&error, nr, sql_mode_for_dates(get_thd()));
return store_TIME_with_warning(rc ? NULL : &ltime, &str, error); return store_TIME_with_warning(&dt, &str, error);
} }
int Field_temporal_with_date::store(longlong nr, bool unsigned_val) int Field_temporal_with_date::store(longlong nr, bool unsigned_val)
{ {
int error; int error;
MYSQL_TIME ltime;
THD *thd= get_thd();
ErrConvInteger str(nr, unsigned_val); ErrConvInteger str(nr, unsigned_val);
bool rc= Sec6(nr, unsigned_val).to_datetime(&ltime, sql_mode_for_dates(thd), Datetime dt(&error, nr, sql_mode_for_dates(get_thd()));
&error); return store_TIME_with_warning(&dt, &str, error);
return store_TIME_with_warning(rc ? NULL : &ltime, &str, error);
} }
int Field_temporal_with_date::store_time_dec(const MYSQL_TIME *ltime, uint dec) int Field_temporal_with_date::store_time_dec(const MYSQL_TIME *ltime, uint dec)
{ {
int error; int error;
ErrConvTime str(ltime); ErrConvTime str(ltime);
THD *thd= get_thd(); THD *thd= get_thd();
Datetime dt(thd, &error, ltime, sql_mode_for_dates(thd)); Datetime dt(thd, &error, ltime, sql_mode_for_dates(thd));
ltime= dt.is_valid_datetime() ? dt.get_mysql_time() : NULL; return store_TIME_with_warning(&dt, &str, error);
return store_TIME_with_warning(const_cast<MYSQL_TIME*>(ltime), &str, error);
} }
...@@ -5708,34 +5686,28 @@ Item *Field_temporal::get_equal_const_item_datetime(THD *thd, ...@@ -5708,34 +5686,28 @@ Item *Field_temporal::get_equal_const_item_datetime(THD *thd,
** In number context: HHMMSS ** In number context: HHMMSS
** Stored as a 3 byte unsigned int ** Stored as a 3 byte unsigned int
****************************************************************************/ ****************************************************************************/
int Field_time::store_TIME_with_warning(MYSQL_TIME *ltime, int Field_time::store_TIME_with_warning(const Time *t,
const ErrConv *str, int was_cut) const ErrConv *str, int warn)
{ {
ASSERT_COLUMN_MARKED_FOR_WRITE; ASSERT_COLUMN_MARKED_FOR_WRITE;
// Handle totally bad values
if (!ltime) if (!t->is_valid_time())
{ {
Datetime tmp; static const Datetime zero;
store_TIME(const_cast<MYSQL_TIME*>(tmp.get_mysql_time())); store_TIME(zero.get_mysql_time());
set_warnings(Sql_condition::WARN_LEVEL_WARN, str, MYSQL_TIME_WARN_TRUNCATED); set_warnings(Sql_condition::WARN_LEVEL_WARN, str, MYSQL_TIME_WARN_TRUNCATED);
return 1; return 1;
} }
if (ltime->year != 0 || ltime->month != 0) // Adjust and store the value
{ if (t->fraction_remainder(decimals()))
ltime->year= ltime->month= ltime->day= 0;
was_cut|= MYSQL_TIME_NOTE_TRUNCATED;
}
my_time_trunc(ltime, decimals());
store_TIME(ltime);
if (!MYSQL_TIME_WARN_HAVE_WARNINGS(was_cut) &&
MYSQL_TIME_WARN_HAVE_NOTES(was_cut))
{ {
set_warnings(Sql_condition::WARN_LEVEL_NOTE, str, Time truncated(t->trunc(decimals()));
was_cut | MYSQL_TIME_WARN_TRUNCATED); store_TIME(truncated.get_mysql_time());
return 3;
} }
set_warnings(Sql_condition::WARN_LEVEL_WARN, str, was_cut); else
return was_cut ? 2 : 0; store_TIME(t->get_mysql_time());
// Calculate return value and send warnings if needed
return store_TIME_return_code_with_warnings(warn, str, MYSQL_TIMESTAMP_TIME);
} }
...@@ -5752,12 +5724,10 @@ void Field_time::store_TIME(const MYSQL_TIME *ltime) ...@@ -5752,12 +5724,10 @@ void Field_time::store_TIME(const MYSQL_TIME *ltime)
int Field_time::store(const char *from,size_t len,CHARSET_INFO *cs) int Field_time::store(const char *from,size_t len,CHARSET_INFO *cs)
{ {
MYSQL_TIME ltime;
MYSQL_TIME_STATUS status;
ErrConvString str(from, len, cs); ErrConvString str(from, len, cs);
bool rc= str_to_time(cs, from, len, &ltime, sql_mode_for_dates(get_thd()), int error;
&status); Time tm(&error, from, len, cs, sql_mode_for_dates(get_thd()));
return store_TIME_with_warning(rc ? NULL : &ltime, &str, status.warnings); return store_TIME_with_warning(&tm, &str, error);
} }
...@@ -5766,28 +5736,25 @@ int Field_time::store_time_dec(const MYSQL_TIME *ltime, uint dec) ...@@ -5766,28 +5736,25 @@ int Field_time::store_time_dec(const MYSQL_TIME *ltime, uint dec)
ErrConvTime str(ltime); ErrConvTime str(ltime);
int warn; int warn;
Time tm(&warn, ltime, curdays); Time tm(&warn, ltime, curdays);
ltime= tm.is_valid_time() ? tm.get_mysql_time() : NULL; return store_TIME_with_warning(&tm, &str, warn);
return store_TIME_with_warning(const_cast<MYSQL_TIME *>(ltime), &str, warn);
} }
int Field_time::store(double nr) int Field_time::store(double nr)
{ {
MYSQL_TIME ltime;
ErrConvDouble str(nr); ErrConvDouble str(nr);
int was_cut; int was_cut;
bool rc= Sec6(nr).to_time(&ltime, &was_cut); Time tm(&was_cut, nr);
return store_TIME_with_warning(rc ? NULL : &ltime, &str, was_cut); return store_TIME_with_warning(&tm, &str, was_cut);
} }
int Field_time::store(longlong nr, bool unsigned_val) int Field_time::store(longlong nr, bool unsigned_val)
{ {
MYSQL_TIME ltime;
ErrConvInteger str(nr, unsigned_val); ErrConvInteger str(nr, unsigned_val);
int was_cut; int was_cut;
bool rc= Sec6(nr, unsigned_val).to_time(&ltime, &was_cut); Time tm(&was_cut, nr, unsigned_val);
return store_TIME_with_warning(rc ? NULL : &ltime, &str, was_cut); return store_TIME_with_warning(&tm, &str, was_cut);
} }
...@@ -5943,10 +5910,9 @@ void Field_time_hires::store_TIME(const MYSQL_TIME *ltime) ...@@ -5943,10 +5910,9 @@ void Field_time_hires::store_TIME(const MYSQL_TIME *ltime)
int Field_time::store_decimal(const my_decimal *d) int Field_time::store_decimal(const my_decimal *d)
{ {
ErrConvDecimal str(d); ErrConvDecimal str(d);
MYSQL_TIME ltime;
int was_cut; int was_cut;
bool rc= Sec6(d).to_time(&ltime, &was_cut); Time tm(&was_cut, d);
return store_TIME_with_warning(rc ? NULL : &ltime, &str, was_cut); return store_TIME_with_warning(&tm, &str, was_cut);
} }
...@@ -6268,7 +6234,7 @@ void Field_year::sql_type(String &res) const ...@@ -6268,7 +6234,7 @@ void Field_year::sql_type(String &res) const
** Stored as a 4 byte unsigned int ** Stored as a 4 byte unsigned int
****************************************************************************/ ****************************************************************************/
void Field_date::store_TIME(MYSQL_TIME *ltime) void Field_date::store_TIME(const MYSQL_TIME *ltime)
{ {
uint tmp= ltime->year*10000L + ltime->month*100+ltime->day; uint tmp= ltime->year*10000L + ltime->month*100+ltime->day;
int4store(ptr,tmp); int4store(ptr,tmp);
...@@ -6361,7 +6327,7 @@ void Field_date::sql_type(String &res) const ...@@ -6361,7 +6327,7 @@ void Field_date::sql_type(String &res) const
** In number context: YYYYMMDD ** In number context: YYYYMMDD
****************************************************************************/ ****************************************************************************/
void Field_newdate::store_TIME(MYSQL_TIME *ltime) void Field_newdate::store_TIME(const MYSQL_TIME *ltime)
{ {
uint tmp= ltime->year*16*32 + ltime->month*32+ltime->day; uint tmp= ltime->year*16*32 + ltime->month*32+ltime->day;
int3store(ptr,tmp); int3store(ptr,tmp);
...@@ -6512,7 +6478,7 @@ Item *Field_newdate::get_equal_const_item(THD *thd, const Context &ctx, ...@@ -6512,7 +6478,7 @@ Item *Field_newdate::get_equal_const_item(THD *thd, const Context &ctx,
** Stored as a 8 byte unsigned int. Should sometimes be change to a 6 byte int. ** Stored as a 8 byte unsigned int. Should sometimes be change to a 6 byte int.
****************************************************************************/ ****************************************************************************/
void Field_datetime::store_TIME(MYSQL_TIME *ltime) void Field_datetime::store_TIME(const MYSQL_TIME *ltime)
{ {
ulonglong tmp= TIME_to_ulonglong_datetime(ltime); ulonglong tmp= TIME_to_ulonglong_datetime(ltime);
int8store(ptr,tmp); int8store(ptr,tmp);
...@@ -6650,13 +6616,14 @@ int Field_datetime::set_time() ...@@ -6650,13 +6616,14 @@ int Field_datetime::set_time()
thd->variables.time_zone->gmt_sec_to_TIME(&now_time, thd->query_start()); thd->variables.time_zone->gmt_sec_to_TIME(&now_time, thd->query_start());
now_time.second_part= thd->query_start_sec_part(); now_time.second_part= thd->query_start_sec_part();
set_notnull(); set_notnull();
my_time_trunc(&now_time, decimals());
store_TIME(&now_time); store_TIME(&now_time);
thd->time_zone_used= 1; thd->time_zone_used= 1;
return 0; return 0;
} }
void Field_datetime_hires::store_TIME(MYSQL_TIME *ltime) void Field_datetime_hires::store_TIME(const MYSQL_TIME *ltime)
{ {
ulonglong packed= sec_part_shift(pack_time(ltime), dec); ulonglong packed= sec_part_shift(pack_time(ltime), dec);
store_bigendian(packed, ptr, Field_datetime_hires::pack_length()); store_bigendian(packed, ptr, Field_datetime_hires::pack_length());
...@@ -6665,11 +6632,9 @@ void Field_datetime_hires::store_TIME(MYSQL_TIME *ltime) ...@@ -6665,11 +6632,9 @@ void Field_datetime_hires::store_TIME(MYSQL_TIME *ltime)
int Field_temporal_with_date::store_decimal(const my_decimal *d) int Field_temporal_with_date::store_decimal(const my_decimal *d)
{ {
int error; int error;
MYSQL_TIME ltime;
THD *thd= get_thd();
ErrConvDecimal str(d); ErrConvDecimal str(d);
bool rc= Sec6(d).to_datetime(&ltime, sql_mode_for_dates(thd), &error); Datetime tm(&error, d, sql_mode_for_dates(get_thd()));
return store_TIME_with_warning(rc ? NULL : &ltime, &str, error); return store_TIME_with_warning(&tm, &str, error);
} }
bool Field_datetime_with_dec::send_binary(Protocol *protocol) bool Field_datetime_with_dec::send_binary(Protocol *protocol)
...@@ -6742,9 +6707,8 @@ int Field_datetimef::reset() ...@@ -6742,9 +6707,8 @@ int Field_datetimef::reset()
return 0; return 0;
} }
void Field_datetimef::store_TIME(MYSQL_TIME *ltime) void Field_datetimef::store_TIME(const MYSQL_TIME *ltime)
{ {
my_time_trunc(ltime, decimals());
longlong tmp= TIME_to_longlong_datetime_packed(ltime); longlong tmp= TIME_to_longlong_datetime_packed(ltime);
my_datetime_packed_to_binary(tmp, ptr, dec); my_datetime_packed_to_binary(tmp, ptr, dec);
} }
......
...@@ -2595,6 +2595,20 @@ class Field_temporal: public Field { ...@@ -2595,6 +2595,20 @@ class Field_temporal: public Field {
protected: protected:
Item *get_equal_const_item_datetime(THD *thd, const Context &ctx, Item *get_equal_const_item_datetime(THD *thd, const Context &ctx,
Item *const_item); Item *const_item);
int store_TIME_return_code_with_warnings(int warn, const ErrConv *str,
timestamp_type ts_type)
{
if (!MYSQL_TIME_WARN_HAVE_WARNINGS(warn) &&
MYSQL_TIME_WARN_HAVE_NOTES(warn))
{
set_warnings(Sql_condition::WARN_LEVEL_NOTE, str,
warn | MYSQL_TIME_WARN_TRUNCATED, ts_type);
return 3;
}
set_warnings(Sql_condition::WARN_LEVEL_WARN, str, warn, ts_type);
return warn ? 2 : 0;
}
public: public:
Field_temporal(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, Field_temporal(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg, uchar null_bit_arg, utype unireg_check_arg,
...@@ -2660,9 +2674,10 @@ class Field_temporal: public Field { ...@@ -2660,9 +2674,10 @@ class Field_temporal: public Field {
*/ */
class Field_temporal_with_date: public Field_temporal { class Field_temporal_with_date: public Field_temporal {
protected: protected:
int store_TIME_with_warning(MYSQL_TIME *ltime, const ErrConv *str, int store_TIME_with_warning(const Datetime *ltime, const ErrConv *str,
int was_cut); int was_cut);
virtual void store_TIME(MYSQL_TIME *ltime) = 0; void store_TIME_with_trunc(const Time *);
virtual void store_TIME(const MYSQL_TIME *ltime) = 0;
virtual bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, virtual bool get_TIME(MYSQL_TIME *ltime, const uchar *pos,
ulonglong fuzzydate) const = 0; ulonglong fuzzydate) const = 0;
bool validate_MMDD(bool not_zero_date, uint month, uint day, bool validate_MMDD(bool not_zero_date, uint month, uint day,
...@@ -2694,7 +2709,8 @@ class Field_temporal_with_date: public Field_temporal { ...@@ -2694,7 +2709,8 @@ class Field_temporal_with_date: public Field_temporal {
class Field_timestamp :public Field_temporal { class Field_timestamp :public Field_temporal {
protected: protected:
sql_mode_t sql_mode_for_timestamp(THD *thd) const; sql_mode_t sql_mode_for_timestamp(THD *thd) const;
int store_TIME_with_warning(THD *, MYSQL_TIME *, const ErrConv *, int warn); int store_TIME_with_warning(THD *, const Datetime *,
const ErrConv *, int warn);
public: public:
Field_timestamp(uchar *ptr_arg, uint32 len_arg, Field_timestamp(uchar *ptr_arg, uint32 len_arg,
uchar *null_ptr_arg, uchar null_bit_arg, uchar *null_ptr_arg, uchar null_bit_arg,
...@@ -2948,7 +2964,7 @@ class Field_date_common: public Field_temporal_with_date ...@@ -2948,7 +2964,7 @@ class Field_date_common: public Field_temporal_with_date
class Field_date :public Field_date_common class Field_date :public Field_date_common
{ {
void store_TIME(MYSQL_TIME *ltime); void store_TIME(const MYSQL_TIME *ltime);
bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const; bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const;
public: public:
Field_date(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, Field_date(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
...@@ -2984,7 +3000,7 @@ class Field_date :public Field_date_common ...@@ -2984,7 +3000,7 @@ class Field_date :public Field_date_common
class Field_newdate :public Field_date_common class Field_newdate :public Field_date_common
{ {
void store_TIME(MYSQL_TIME *ltime); void store_TIME(const MYSQL_TIME *ltime);
bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const; bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const;
public: public:
Field_newdate(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, Field_newdate(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
...@@ -3019,7 +3035,7 @@ class Field_time :public Field_temporal { ...@@ -3019,7 +3035,7 @@ class Field_time :public Field_temporal {
long curdays; long curdays;
protected: protected:
virtual void store_TIME(const MYSQL_TIME *ltime); virtual void store_TIME(const MYSQL_TIME *ltime);
int store_TIME_with_warning(MYSQL_TIME *ltime, const ErrConv *str, int warn); int store_TIME_with_warning(const Time *ltime, const ErrConv *str, int warn);
void set_warnings(Sql_condition::enum_warning_level level, void set_warnings(Sql_condition::enum_warning_level level,
const ErrConv *str, int was_cut) const ErrConv *str, int was_cut)
{ {
...@@ -3177,7 +3193,7 @@ class Field_timef :public Field_time_with_dec { ...@@ -3177,7 +3193,7 @@ class Field_timef :public Field_time_with_dec {
class Field_datetime :public Field_temporal_with_date { class Field_datetime :public Field_temporal_with_date {
void store_TIME(MYSQL_TIME *ltime); void store_TIME(const MYSQL_TIME *ltime);
bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const; bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const;
public: public:
Field_datetime(uchar *ptr_arg, uint length_arg, uchar *null_ptr_arg, Field_datetime(uchar *ptr_arg, uint length_arg, uchar *null_ptr_arg,
...@@ -3270,7 +3286,7 @@ class Field_datetime_with_dec :public Field_datetime { ...@@ -3270,7 +3286,7 @@ class Field_datetime_with_dec :public Field_datetime {
DATETIME(1..6) DATETIME(1..6)
*/ */
class Field_datetime_hires :public Field_datetime_with_dec { class Field_datetime_hires :public Field_datetime_with_dec {
void store_TIME(MYSQL_TIME *ltime); void store_TIME(const MYSQL_TIME *ltime);
bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const; bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const;
public: public:
Field_datetime_hires(uchar *ptr_arg, uchar *null_ptr_arg, Field_datetime_hires(uchar *ptr_arg, uchar *null_ptr_arg,
...@@ -3293,7 +3309,7 @@ class Field_datetime_hires :public Field_datetime_with_dec { ...@@ -3293,7 +3309,7 @@ class Field_datetime_hires :public Field_datetime_with_dec {
DATETIME(0..6) - MySQL56 version DATETIME(0..6) - MySQL56 version
*/ */
class Field_datetimef :public Field_datetime_with_dec { class Field_datetimef :public Field_datetime_with_dec {
void store_TIME(MYSQL_TIME *ltime); void store_TIME(const MYSQL_TIME *ltime);
bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const; bool get_TIME(MYSQL_TIME *ltime, const uchar *pos, ulonglong fuzzydate) const;
int save_field_metadata(uchar *metadata_ptr) int save_field_metadata(uchar *metadata_ptr)
{ {
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "sql_time.h" #include "sql_time.h"
#include "item.h" #include "item.h"
#include "log.h" #include "log.h"
#include "tztime.h"
Type_handler_row type_handler_row; Type_handler_row type_handler_row;
...@@ -359,12 +360,13 @@ VYear_op::VYear_op(Item_func_hybrid_field_type *item) ...@@ -359,12 +360,13 @@ VYear_op::VYear_op(Item_func_hybrid_field_type *item)
{ } { }
void Time::make_from_item(Item *item, const Options opt) void Time::make_from_item(int *warn, Item *item, const Options opt)
{ {
*warn= 0;
if (item->get_date(this, opt.get_date_flags())) if (item->get_date(this, opt.get_date_flags()))
time_type= MYSQL_TIMESTAMP_NONE; time_type= MYSQL_TIMESTAMP_NONE;
else else
valid_MYSQL_TIME_to_valid_value(opt); valid_MYSQL_TIME_to_valid_value(warn, opt);
} }
......
...@@ -466,6 +466,10 @@ class Temporal: protected MYSQL_TIME ...@@ -466,6 +466,10 @@ class Temporal: protected MYSQL_TIME
time_type= MYSQL_TIMESTAMP_NONE; time_type= MYSQL_TIMESTAMP_NONE;
} }
public: public:
long fraction_remainder(uint dec) const
{
return my_time_fraction_remainder(second_part, dec);
}
}; };
...@@ -474,7 +478,7 @@ class Temporal: protected MYSQL_TIME ...@@ -474,7 +478,7 @@ class Temporal: protected MYSQL_TIME
using Item's native timestamp type, without automatic timestamp using Item's native timestamp type, without automatic timestamp
type conversion. type conversion.
*/ */
class Temporal_hybrid: private Temporal class Temporal_hybrid: public Temporal
{ {
public: public:
Temporal_hybrid(THD *thd, Item *item); Temporal_hybrid(THD *thd, Item *item);
...@@ -524,7 +528,7 @@ class Temporal_hybrid: private Temporal ...@@ -524,7 +528,7 @@ class Temporal_hybrid: private Temporal
Time derives from MYSQL_TIME privately to make sure it is accessed Time derives from MYSQL_TIME privately to make sure it is accessed
externally only in the valid state. externally only in the valid state.
*/ */
class Time: private Temporal class Time: public Temporal
{ {
public: public:
enum datetime_to_time_mode_t enum datetime_to_time_mode_t
...@@ -599,30 +603,27 @@ class Time: private Temporal ...@@ -599,30 +603,27 @@ class Time: private Temporal
/* /*
Convert a valid DATE or DATETIME to TIME. Convert a valid DATE or DATETIME to TIME.
Before this call, "this" must be a valid DATE or DATETIME value, Before this call, "this" must be a valid DATE or DATETIME value,
e.g. returned from Item::get_date(). e.g. returned from Item::get_date(), str_to_time(), number_to_time().
After this call, "this" is a valid TIME value. After this call, "this" is a valid TIME value.
*/ */
void valid_datetime_to_valid_time(const Options opt) void valid_datetime_to_valid_time(int *warn, const Options opt)
{ {
DBUG_ASSERT(time_type == MYSQL_TIMESTAMP_DATE || DBUG_ASSERT(time_type == MYSQL_TIMESTAMP_DATE ||
time_type == MYSQL_TIMESTAMP_DATETIME); time_type == MYSQL_TIMESTAMP_DATETIME);
/* /*
Make sure that day and hour are valid, so the result hour value We're dealing with a DATE or DATETIME returned from
str_to_time(), number_to_time() or unpack_time().
Do some asserts to make sure the result hour value
after mixing days to hours does not go out of the valid TIME range. after mixing days to hours does not go out of the valid TIME range.
The maximum hour value after mixing days will be 31*24+23=767,
which is within the supported TIME range.
Thus no adjust_time_range_or_invalidate() is needed here.
*/ */
DBUG_ASSERT(day < 32); DBUG_ASSERT(day < 32);
DBUG_ASSERT(hour < 24); DBUG_ASSERT(hour < 24);
if (year == 0 && month == 0 && if (opt.datetime_to_time_mode() ==
opt.datetime_to_time_mode() ==
DATETIME_TO_TIME_YYYYMMDD_000000DD_MIX_TO_HOURS) DATETIME_TO_TIME_YYYYMMDD_000000DD_MIX_TO_HOURS)
{ datetime_to_time_YYYYMMDD_000000DD_mix_to_hours(warn, year, month, day);
/*
The maximum hour value after mixing days will be 31*24+23=767,
which is within the supported TIME range.
Thus no adjust_time_range_or_invalidate() is needed here.
*/
hour+= day * 24;
}
year= month= day= 0; year= month= day= 0;
time_type= MYSQL_TIMESTAMP_TIME; time_type= MYSQL_TIMESTAMP_TIME;
DBUG_ASSERT(is_valid_time_slow()); DBUG_ASSERT(is_valid_time_slow());
...@@ -630,6 +631,7 @@ class Time: private Temporal ...@@ -630,6 +631,7 @@ class Time: private Temporal
/** /**
Convert valid DATE/DATETIME to valid TIME if needed. Convert valid DATE/DATETIME to valid TIME if needed.
This method is called after Item::get_date(), This method is called after Item::get_date(),
str_to_time(), number_to_time().
which can return only valid TIME/DATE/DATETIME values. which can return only valid TIME/DATE/DATETIME values.
Before this call, "this" is: Before this call, "this" is:
- either a valid TIME/DATE/DATETIME value - either a valid TIME/DATE/DATETIME value
...@@ -639,12 +641,12 @@ class Time: private Temporal ...@@ -639,12 +641,12 @@ class Time: private Temporal
- either a valid TIME (within the supported TIME range), - either a valid TIME (within the supported TIME range),
- or MYSQL_TIMESTAMP_NONE - or MYSQL_TIMESTAMP_NONE
*/ */
void valid_MYSQL_TIME_to_valid_value(const Options opt) void valid_MYSQL_TIME_to_valid_value(int *warn, const Options opt)
{ {
switch (time_type) { switch (time_type) {
case MYSQL_TIMESTAMP_DATE: case MYSQL_TIMESTAMP_DATE:
case MYSQL_TIMESTAMP_DATETIME: case MYSQL_TIMESTAMP_DATETIME:
valid_datetime_to_valid_time(opt); valid_datetime_to_valid_time(warn, opt);
break; break;
case MYSQL_TIMESTAMP_NONE: case MYSQL_TIMESTAMP_NONE:
break; break;
...@@ -656,6 +658,19 @@ class Time: private Temporal ...@@ -656,6 +658,19 @@ class Time: private Temporal
break; break;
} }
} }
/*
This method is called after number_to_time() and str_to_time(),
which can return DATE or DATETIME values. Convert to TIME if needed.
We trust that xxx_to_time() returns a valid TIME/DATE/DATETIME value,
so here we need to do only simple validation.
*/
void xxx_to_time_result_to_valid_value(int *warn, const Options opt)
{
// str_to_time(), number_to_time() never return MYSQL_TIMESTAMP_ERROR
DBUG_ASSERT(time_type != MYSQL_TIMESTAMP_ERROR);
valid_MYSQL_TIME_to_valid_value(warn, opt);
}
void adjust_time_range_or_invalidate(int *warn) void adjust_time_range_or_invalidate(int *warn)
{ {
if (check_time_range(this, TIME_SECOND_PART_DIGITS, warn)) if (check_time_range(this, TIME_SECOND_PART_DIGITS, warn))
...@@ -667,12 +682,49 @@ class Time: private Temporal ...@@ -667,12 +682,49 @@ class Time: private Temporal
long curdays); long curdays);
void make_from_time(int *warn, const MYSQL_TIME *from); void make_from_time(int *warn, const MYSQL_TIME *from);
void make_from_datetime(int *warn, const MYSQL_TIME *from, long curdays); void make_from_datetime(int *warn, const MYSQL_TIME *from, long curdays);
void make_from_item(class Item *item, const Options opt); void make_from_item(int *warn, Item *item, const Options opt);
public: public:
/*
All constructors that accept an "int *warn" parameter initialize *warn.
The old value gets lost.
*/
Time() { time_type= MYSQL_TIMESTAMP_NONE; } Time() { time_type= MYSQL_TIMESTAMP_NONE; }
Time(Item *item) { make_from_item(item, Options()); } Time(Item *item)
Time(Item *item, const Options opt) { make_from_item(item, opt); } {
int warn;
make_from_item(&warn, item, Options());
}
Time(Item *item, const Options opt)
{
int warn;
make_from_item(&warn, item, opt);
}
Time(int *warn, const MYSQL_TIME *from, long curdays); Time(int *warn, const MYSQL_TIME *from, long curdays);
Time(int *warn, const char *str, uint len, CHARSET_INFO *cs,
const Options opt)
{
MYSQL_TIME_STATUS status;
if (str_to_time(cs, str, len, this, opt.get_date_flags(), &status))
time_type= MYSQL_TIMESTAMP_NONE;
// The below call will optionally add notes to already collected warnings:
xxx_to_time_result_to_valid_value(&status.warnings, opt);
*warn= status.warnings;
}
Time(int *warn, const Sec6 &nr, const Options opt)
{
if (nr.to_time(this, warn))
time_type= MYSQL_TIMESTAMP_NONE;
xxx_to_time_result_to_valid_value(warn, opt);
}
Time(int *warn, double nr)
:Temporal(Time(warn, Sec6(nr), Options()))
{ }
Time(int *warn, longlong nr, bool unsigned_val)
:Temporal(Time(warn, Sec6(nr, unsigned_val), Options()))
{ }
Time(int *warn, const my_decimal *d)
:Temporal(Time(warn, Sec6(d), Options()))
{ }
static sql_mode_t flags_for_get_date() static sql_mode_t flags_for_get_date()
{ return TIME_TIME_ONLY | TIME_INVALID_DATES; } { return TIME_TIME_ONLY | TIME_INVALID_DATES; }
static sql_mode_t comparison_flags_for_get_date() static sql_mode_t comparison_flags_for_get_date()
...@@ -748,6 +800,12 @@ class Time: private Temporal ...@@ -748,6 +800,12 @@ class Time: private Temporal
{ {
return is_valid_time() ? Temporal::to_packed() : 0; return is_valid_time() ? Temporal::to_packed() : 0;
} }
Time trunc(uint dec) const
{
Time tm(*this);
my_time_trunc(&tm, dec);
return tm;
}
}; };
...@@ -774,7 +832,7 @@ class Time: private Temporal ...@@ -774,7 +832,7 @@ class Time: private Temporal
it is accessed externally only in the valid state. it is accessed externally only in the valid state.
*/ */
class Temporal_with_date: protected Temporal class Temporal_with_date: public Temporal
{ {
protected: protected:
void check_date_or_invalidate(int *warn, sql_mode_t flags); void check_date_or_invalidate(int *warn, sql_mode_t flags);
...@@ -792,6 +850,21 @@ class Temporal_with_date: protected Temporal ...@@ -792,6 +850,21 @@ class Temporal_with_date: protected Temporal
{ {
make_from_item(thd, item); make_from_item(thd, item);
} }
Temporal_with_date(int *warn, const Sec6 &nr, sql_mode_t flags)
{
DBUG_ASSERT((flags & TIME_TIME_ONLY) == 0);
if (nr.to_datetime(this, flags, warn))
time_type= MYSQL_TIMESTAMP_NONE;
}
Temporal_with_date(int *warn, const char *str, uint len, CHARSET_INFO *cs,
sql_mode_t flags)
{
DBUG_ASSERT((flags & TIME_TIME_ONLY) == 0);
MYSQL_TIME_STATUS status;
if (str_to_datetime(cs, str, len, this, flags, &status))
time_type= MYSQL_TIMESTAMP_NONE;
*warn= status.warnings;
}
public: public:
bool check_date_with_warn(ulonglong flags) bool check_date_with_warn(ulonglong flags)
{ {
...@@ -916,6 +989,11 @@ class Datetime: public Temporal_with_date ...@@ -916,6 +989,11 @@ class Datetime: public Temporal_with_date
DBUG_ASSERT(time_type == MYSQL_TIMESTAMP_DATETIME); DBUG_ASSERT(time_type == MYSQL_TIMESTAMP_DATETIME);
return !check_datetime_range(this); return !check_datetime_range(this);
} }
void date_to_datetime_if_needed()
{
if (time_type == MYSQL_TIMESTAMP_DATE)
date_to_datetime(this);
}
void make_from_time(THD *thd, int *warn, const MYSQL_TIME *from, void make_from_time(THD *thd, int *warn, const MYSQL_TIME *from,
sql_mode_t flags); sql_mode_t flags);
void make_from_datetime(THD *thd, int *warn, const MYSQL_TIME *from, void make_from_datetime(THD *thd, int *warn, const MYSQL_TIME *from,
...@@ -924,22 +1002,19 @@ class Datetime: public Temporal_with_date ...@@ -924,22 +1002,19 @@ class Datetime: public Temporal_with_date
Datetime(THD *thd, Item *item, sql_mode_t flags) Datetime(THD *thd, Item *item, sql_mode_t flags)
:Temporal_with_date(thd, item, flags) :Temporal_with_date(thd, item, flags)
{ {
if (time_type == MYSQL_TIMESTAMP_DATE) date_to_datetime_if_needed();
date_to_datetime(this);
DBUG_ASSERT(is_valid_value_slow()); DBUG_ASSERT(is_valid_value_slow());
} }
Datetime(THD *thd, Item *item) Datetime(THD *thd, Item *item)
:Temporal_with_date(thd, item) :Temporal_with_date(thd, item)
{ {
if (time_type == MYSQL_TIMESTAMP_DATE) date_to_datetime_if_needed();
date_to_datetime(this);
DBUG_ASSERT(is_valid_value_slow()); DBUG_ASSERT(is_valid_value_slow());
} }
Datetime(Item *item) Datetime(Item *item)
:Temporal_with_date(current_thd, item) :Temporal_with_date(current_thd, item)
{ {
if (time_type == MYSQL_TIMESTAMP_DATE) date_to_datetime_if_needed();
date_to_datetime(this);
DBUG_ASSERT(is_valid_value_slow()); DBUG_ASSERT(is_valid_value_slow());
} }
Datetime(THD *thd, int *warn, const MYSQL_TIME *from, sql_mode_t flags); Datetime(THD *thd, int *warn, const MYSQL_TIME *from, sql_mode_t flags);
...@@ -947,6 +1022,39 @@ class Datetime: public Temporal_with_date ...@@ -947,6 +1022,39 @@ class Datetime: public Temporal_with_date
{ {
set_zero_time(this, MYSQL_TIMESTAMP_DATETIME); set_zero_time(this, MYSQL_TIMESTAMP_DATETIME);
} }
Datetime(int *warn, const char *str, uint len, CHARSET_INFO *cs,
sql_mode_t flags)
:Temporal_with_date(warn, str, len, cs, flags)
{
date_to_datetime_if_needed();
DBUG_ASSERT(is_valid_value_slow());
}
Datetime(int *warn, double nr, sql_mode_t flags)
:Temporal_with_date(warn, Sec6(nr), flags)
{
date_to_datetime_if_needed();
DBUG_ASSERT(is_valid_value_slow());
}
Datetime(int *warn, const my_decimal *d, sql_mode_t flags)
:Temporal_with_date(warn, Sec6(d), flags)
{
date_to_datetime_if_needed();
DBUG_ASSERT(is_valid_value_slow());
}
/*
Create a Datime object from a longlong number.
Note, unlike in Time(), we don't need an "unsigned_val" here,
as it's not important if overflow happened because
of a negative number, or because of a huge positive number.
*/
Datetime(int *warn, longlong sec, ulong usec, sql_mode_t flags)
:Temporal_with_date(warn, Sec6(false, (ulonglong) sec, usec), flags)
{
Sec6 nr(false, (ulonglong) sec, usec);
date_to_datetime_if_needed();
DBUG_ASSERT(is_valid_value_slow());
}
bool is_valid_datetime() const bool is_valid_datetime() const
{ {
/* /*
...@@ -1019,6 +1127,12 @@ class Datetime: public Temporal_with_date ...@@ -1019,6 +1127,12 @@ class Datetime: public Temporal_with_date
{ {
return is_valid_datetime() ? Temporal::to_packed() : 0; return is_valid_datetime() ? Temporal::to_packed() : 0;
} }
Datetime trunc(uint dec) const
{
Datetime tm(*this);
my_time_trunc(&tm, dec);
return tm;
}
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment