Commit d2bba4ce authored by Alexander Barkov's avatar Alexander Barkov

MDEV-16928 Move MYSQL_TIME initialization from Field_xxx::store_time_dec() to...

MDEV-16928 Move MYSQL_TIME initialization from Field_xxx::store_time_dec() to new constructors Time() and Datetime()
parent ffdae1a9
This diff is collapsed.
...@@ -2661,7 +2661,7 @@ class Field_temporal: public Field { ...@@ -2661,7 +2661,7 @@ 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(MYSQL_TIME *ltime, const ErrConv *str,
int was_cut, int have_smth_to_conv); int was_cut);
virtual void store_TIME(MYSQL_TIME *ltime) = 0; virtual void store_TIME(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;
...@@ -2694,8 +2694,7 @@ class Field_temporal_with_date: public Field_temporal { ...@@ -2694,8 +2694,7 @@ 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 store_TIME_with_warning(THD *, MYSQL_TIME *, const ErrConv *, int warn);
int warnings, bool have_smth_to_conv);
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,
...@@ -3020,8 +3019,7 @@ class Field_time :public Field_temporal { ...@@ -3020,8 +3019,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 store_TIME_with_warning(MYSQL_TIME *ltime, const ErrConv *str, int warn);
int was_cut, int have_smth_to_conv);
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)
{ {
......
...@@ -368,6 +368,105 @@ void Time::make_from_item(Item *item, const Options opt) ...@@ -368,6 +368,105 @@ void Time::make_from_item(Item *item, const Options opt)
} }
/**
Create from a DATETIME by subtracting a given number of days,
implementing an optimized version of calc_time_diff().
*/
void Time::make_from_datetime_with_days_diff(int *warn, const MYSQL_TIME *from,
long days)
{
*warn= 0;
DBUG_ASSERT(from->time_type == MYSQL_TIMESTAMP_DATETIME ||
from->time_type == MYSQL_TIMESTAMP_DATE);
long daynr= calc_daynr(from->year, from->month, from->day);
long daydiff= daynr - days;
if (!daynr) // Zero date
{
set_zero_time(this, MYSQL_TIMESTAMP_TIME);
neg= true;
hour= TIME_MAX_HOUR + 1; // to report "out of range" in "warn"
}
else if (daydiff >=0)
{
neg= false;
year= month= day= 0;
hhmmssff_copy(from);
hour+= daydiff * 24;
time_type= MYSQL_TIMESTAMP_TIME;
}
else
{
longlong timediff= ((((daydiff * 24LL +
from->hour) * 60LL +
from->minute) * 60LL +
from->second) * 1000000LL +
from->second_part);
unpack_time(timediff, this, MYSQL_TIMESTAMP_TIME);
}
// The above code can generate TIME values outside of the valid TIME range.
adjust_time_range_or_invalidate(warn);
}
void Time::make_from_datetime_move_day_to_hour(int *warn,
const MYSQL_TIME *from)
{
*warn= 0;
DBUG_ASSERT(from->time_type == MYSQL_TIMESTAMP_DATE ||
from->time_type == MYSQL_TIMESTAMP_DATETIME);
time_type= MYSQL_TIMESTAMP_TIME;
neg= false;
year= month= day= 0;
hhmmssff_copy(from);
datetime_to_time_YYYYMMDD_000000DD_mix_to_hours(warn, from->year,
from->month, from->day);
adjust_time_range_or_invalidate(warn);
}
void Time::make_from_datetime(int *warn, const MYSQL_TIME *from, long curdays)
{
if (!curdays)
make_from_datetime_move_day_to_hour(warn, from);
else
make_from_datetime_with_days_diff(warn, from, curdays);
}
void Time::make_from_time(int *warn, const MYSQL_TIME *from)
{
DBUG_ASSERT(from->time_type == MYSQL_TIMESTAMP_TIME);
if (from->year || from->month)
make_from_out_of_range(warn);
else
{
*warn= 0;
DBUG_ASSERT(from->day == 0);
*(static_cast<MYSQL_TIME*>(this))= *from;
adjust_time_range_or_invalidate(warn);
}
}
Time::Time(int *warn, const MYSQL_TIME *from, long curdays)
{
switch (from->time_type) {
case MYSQL_TIMESTAMP_NONE:
case MYSQL_TIMESTAMP_ERROR:
make_from_out_of_range(warn);
break;
case MYSQL_TIMESTAMP_DATE:
case MYSQL_TIMESTAMP_DATETIME:
make_from_datetime(warn, from, curdays);
break;
case MYSQL_TIMESTAMP_TIME:
make_from_time(warn, from);
break;
}
DBUG_ASSERT(is_valid_value_slow());
}
void Temporal_with_date::make_from_item(THD *thd, Item *item, sql_mode_t flags) void Temporal_with_date::make_from_item(THD *thd, Item *item, sql_mode_t flags)
{ {
flags&= ~TIME_TIME_ONLY; flags&= ~TIME_TIME_ONLY;
...@@ -400,6 +499,65 @@ void Temporal_with_date::make_from_item(THD *thd, Item *item) ...@@ -400,6 +499,65 @@ void Temporal_with_date::make_from_item(THD *thd, Item *item)
} }
void Temporal_with_date::check_date_or_invalidate(int *warn, sql_mode_t flags)
{
if (check_date(this, pack_time(this) != 0, flags, warn))
time_type= MYSQL_TIMESTAMP_NONE;
}
void Datetime::make_from_time(THD *thd, int *warn, const MYSQL_TIME *from,
sql_mode_t flags)
{
DBUG_ASSERT(from->time_type == MYSQL_TIMESTAMP_TIME);
if (time_to_datetime(thd, from, this))
make_from_out_of_range(warn);
else
{
*warn= 0;
check_date_or_invalidate(warn, flags);
}
}
void Datetime::make_from_datetime(THD *thd, int *warn, const MYSQL_TIME *from,
sql_mode_t flags)
{
DBUG_ASSERT(from->time_type == MYSQL_TIMESTAMP_DATE ||
from->time_type == MYSQL_TIMESTAMP_DATETIME);
if (from->neg || check_datetime_range(from))
make_from_out_of_range(warn);
else
{
*warn= 0;
*(static_cast<MYSQL_TIME*>(this))= *from;
date_to_datetime(this);
check_date_or_invalidate(warn, flags);
}
}
Datetime::Datetime(THD *thd, int *warn, const MYSQL_TIME *from,
sql_mode_t flags)
{
DBUG_ASSERT((flags & TIME_TIME_ONLY) == 0);
switch (from->time_type) {
case MYSQL_TIMESTAMP_ERROR:
case MYSQL_TIMESTAMP_NONE:
make_from_out_of_range(warn);
break;
case MYSQL_TIMESTAMP_TIME:
make_from_time(thd, warn, from, flags);
break;
case MYSQL_TIMESTAMP_DATETIME:
case MYSQL_TIMESTAMP_DATE:
make_from_datetime(thd, warn, from, flags);
break;
}
DBUG_ASSERT(is_valid_value_slow());
}
uint Type_std_attributes::count_max_decimals(Item **item, uint nitems) uint Type_std_attributes::count_max_decimals(Item **item, uint nitems)
{ {
uint res= 0; uint res= 0;
......
...@@ -460,6 +460,11 @@ class Temporal: protected MYSQL_TIME ...@@ -460,6 +460,11 @@ class Temporal: protected MYSQL_TIME
return negate ? -d : d; return negate ? -d : d;
} }
longlong to_packed() const { return ::pack_time(this); } longlong to_packed() const { return ::pack_time(this); }
void make_from_out_of_range(int *warn)
{
*warn= MYSQL_TIME_WARN_OUT_OF_RANGE;
time_type= MYSQL_TIMESTAMP_NONE;
}
public: public:
}; };
...@@ -574,7 +579,23 @@ class Time: private Temporal ...@@ -574,7 +579,23 @@ class Time: private Temporal
second <= TIME_MAX_SECOND && second <= TIME_MAX_SECOND &&
second_part <= TIME_MAX_SECOND_PART; second_part <= TIME_MAX_SECOND_PART;
} }
void hhmmssff_copy(const MYSQL_TIME *from)
{
hour= from->hour;
minute= from->minute;
second= from->second;
second_part= from->second_part;
}
void datetime_to_time_YYYYMMDD_000000DD_mix_to_hours(int *warn,
uint from_year,
uint from_month,
uint from_day)
{
if (from_year != 0 || from_month != 0)
*warn|= MYSQL_TIME_NOTE_TRUNCATED;
else
hour+= from_day * 24;
}
/* /*
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,
...@@ -635,11 +656,23 @@ class Time: private Temporal ...@@ -635,11 +656,23 @@ class Time: private Temporal
break; break;
} }
} }
void adjust_time_range_or_invalidate(int *warn)
{
if (check_time_range(this, TIME_SECOND_PART_DIGITS, warn))
time_type= MYSQL_TIMESTAMP_NONE;
DBUG_ASSERT(is_valid_value_slow());
}
void make_from_datetime_move_day_to_hour(int *warn, const MYSQL_TIME *from);
void make_from_datetime_with_days_diff(int *warn, const MYSQL_TIME *from,
long curdays);
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_item(class Item *item, const Options opt); void make_from_item(class Item *item, const Options opt);
public: public:
Time() { time_type= MYSQL_TIMESTAMP_NONE; } Time() { time_type= MYSQL_TIMESTAMP_NONE; }
Time(Item *item) { make_from_item(item, Options()); } Time(Item *item) { make_from_item(item, Options()); }
Time(Item *item, const Options opt) { make_from_item(item, opt); } Time(Item *item, const Options opt) { make_from_item(item, opt); }
Time(int *warn, const MYSQL_TIME *from, long curdays);
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()
...@@ -744,8 +777,13 @@ class Time: private Temporal ...@@ -744,8 +777,13 @@ class Time: private Temporal
class Temporal_with_date: protected Temporal class Temporal_with_date: protected Temporal
{ {
protected: protected:
void check_date_or_invalidate(int *warn, sql_mode_t flags);
void make_from_item(THD *thd, Item *item, sql_mode_t flags); void make_from_item(THD *thd, Item *item, sql_mode_t flags);
void make_from_item(THD *thd, Item *item); void make_from_item(THD *thd, Item *item);
Temporal_with_date()
{
time_type= MYSQL_TIMESTAMP_NONE;
}
Temporal_with_date(THD *thd, Item *item, sql_mode_t flags) Temporal_with_date(THD *thd, Item *item, sql_mode_t flags)
{ {
make_from_item(thd, item, flags); make_from_item(thd, item, flags);
...@@ -878,6 +916,10 @@ class Datetime: public Temporal_with_date ...@@ -878,6 +916,10 @@ 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 make_from_time(THD *thd, int *warn, const MYSQL_TIME *from,
sql_mode_t flags);
void make_from_datetime(THD *thd, int *warn, const MYSQL_TIME *from,
sql_mode_t flags);
public: public:
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)
...@@ -900,6 +942,11 @@ class Datetime: public Temporal_with_date ...@@ -900,6 +942,11 @@ class Datetime: public Temporal_with_date
date_to_datetime(this); 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()
{
set_zero_time(this, MYSQL_TIMESTAMP_DATETIME);
}
bool is_valid_datetime() const bool is_valid_datetime() const
{ {
/* /*
...@@ -974,6 +1021,7 @@ class Datetime: public Temporal_with_date ...@@ -974,6 +1021,7 @@ class Datetime: public Temporal_with_date
} }
}; };
/* /*
Flags for collation aggregation modes, used in TDCollation::agg(): Flags for collation aggregation modes, used in TDCollation::agg():
......
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