mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-16928 Move MYSQL_TIME initialization from Field_xxx::store_time_dec() to new constructors Time() and Datetime()
This commit is contained in:
180
sql/field.cc
180
sql/field.cc
@ -5021,15 +5021,12 @@ my_time_t Field_timestamp::get_timestamp(const uchar *pos,
|
||||
|
||||
|
||||
int Field_timestamp::store_TIME_with_warning(THD *thd, MYSQL_TIME *l_time,
|
||||
const ErrConv *str,
|
||||
int was_cut,
|
||||
bool have_smth_to_conv)
|
||||
const ErrConv *str, int was_cut)
|
||||
{
|
||||
ASSERT_COLUMN_MARKED_FOR_WRITE;
|
||||
uint error = 0;
|
||||
my_time_t timestamp;
|
||||
|
||||
if (MYSQL_TIME_WARN_HAVE_WARNINGS(was_cut) || !have_smth_to_conv)
|
||||
if (MYSQL_TIME_WARN_HAVE_WARNINGS(was_cut) || !l_time)
|
||||
{
|
||||
error= 1;
|
||||
set_datetime_warning(WARN_DATA_TRUNCATED,
|
||||
@ -5042,10 +5039,10 @@ int Field_timestamp::store_TIME_with_warning(THD *thd, MYSQL_TIME *l_time,
|
||||
str, MYSQL_TIMESTAMP_DATETIME, 1);
|
||||
}
|
||||
/* Only convert a correct date (not a zero date) */
|
||||
if (have_smth_to_conv && l_time->month)
|
||||
if (l_time && l_time->month)
|
||||
{
|
||||
uint conversion_error;
|
||||
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)
|
||||
conversion_error= ER_WARN_DATA_OUT_OF_RANGE;
|
||||
if (unlikely(conversion_error))
|
||||
@ -5054,27 +5051,16 @@ int Field_timestamp::store_TIME_with_warning(THD *thd, MYSQL_TIME *l_time,
|
||||
str, MYSQL_TIMESTAMP_DATETIME, !error);
|
||||
error= 1;
|
||||
}
|
||||
store_TIME(timestamp, l_time->second_part);
|
||||
}
|
||||
else
|
||||
{
|
||||
timestamp= 0;
|
||||
l_time->second_part= 0;
|
||||
store_TIME(0, 0);
|
||||
}
|
||||
store_TIME(timestamp, l_time->second_part);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
copy_or_convert_to_datetime(THD *thd, const MYSQL_TIME *from, MYSQL_TIME *to)
|
||||
{
|
||||
if (from->time_type == MYSQL_TIMESTAMP_TIME)
|
||||
return time_to_datetime(thd, from, to);
|
||||
*to= *from;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
sql_mode_t Field_timestamp::sql_mode_for_timestamp(THD *thd) const
|
||||
{
|
||||
// We don't want to store invalid or fuzzy datetime values in TIMESTAMP
|
||||
@ -5084,14 +5070,13 @@ sql_mode_t Field_timestamp::sql_mode_for_timestamp(THD *thd) const
|
||||
|
||||
int Field_timestamp::store_time_dec(const MYSQL_TIME *ltime, uint dec)
|
||||
{
|
||||
int unused;
|
||||
int warn;
|
||||
ErrConvTime str(ltime);
|
||||
THD *thd= get_thd();
|
||||
MYSQL_TIME l_time;
|
||||
bool valid= !copy_or_convert_to_datetime(thd, ltime, &l_time) &&
|
||||
!check_date(&l_time, pack_time(&l_time) != 0,
|
||||
sql_mode_for_timestamp(thd), &unused);
|
||||
return store_TIME_with_warning(thd, &l_time, &str, false, valid);
|
||||
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, const_cast<MYSQL_TIME*>(ltime),
|
||||
&str, warn);
|
||||
}
|
||||
|
||||
|
||||
@ -5099,14 +5084,12 @@ int Field_timestamp::store(const char *from,size_t len,CHARSET_INFO *cs)
|
||||
{
|
||||
MYSQL_TIME l_time;
|
||||
MYSQL_TIME_STATUS status;
|
||||
bool have_smth_to_conv;
|
||||
ErrConvString str(from, len, cs);
|
||||
THD *thd= get_thd();
|
||||
|
||||
have_smth_to_conv= !str_to_datetime(cs, from, len, &l_time,
|
||||
sql_mode_for_timestamp(thd), &status);
|
||||
return store_TIME_with_warning(thd, &l_time, &str,
|
||||
status.warnings, have_smth_to_conv);
|
||||
bool rc= str_to_datetime(cs, from, len, &l_time,
|
||||
sql_mode_for_timestamp(thd), &status);
|
||||
return store_TIME_with_warning(thd, rc ? NULL : &l_time, &str,
|
||||
status.warnings);
|
||||
}
|
||||
|
||||
|
||||
@ -5117,7 +5100,7 @@ int Field_timestamp::store(double nr)
|
||||
ErrConvDouble str(nr);
|
||||
THD *thd= get_thd();
|
||||
bool rc= Sec6(nr).to_datetime(&l_time, sql_mode_for_timestamp(thd), &error);
|
||||
return store_TIME_with_warning(thd, &l_time, &str, error, !rc);
|
||||
return store_TIME_with_warning(thd, rc ? NULL : &l_time, &str, error);
|
||||
}
|
||||
|
||||
|
||||
@ -5130,7 +5113,7 @@ int Field_timestamp::store(longlong nr, bool unsigned_val)
|
||||
bool rc= Sec6(nr, unsigned_val).to_datetime(&l_time,
|
||||
sql_mode_for_timestamp(thd),
|
||||
&error);
|
||||
return store_TIME_with_warning(thd, &l_time, &str, error, !rc);
|
||||
return store_TIME_with_warning(thd, rc ? NULL : &l_time, &str, error);
|
||||
}
|
||||
|
||||
|
||||
@ -5431,7 +5414,7 @@ int Field_timestamp::store_decimal(const my_decimal *d)
|
||||
THD *thd= get_thd();
|
||||
ErrConvDecimal str(d);
|
||||
bool rc= Sec6(d).to_datetime(<ime, sql_mode_for_timestamp(thd), &error);
|
||||
return store_TIME_with_warning(thd, <ime, &str, error, !rc);
|
||||
return store_TIME_with_warning(thd, rc ? NULL : <ime, &str, error);
|
||||
}
|
||||
|
||||
int Field_timestamp_with_dec::set_time()
|
||||
@ -5557,22 +5540,23 @@ void Field_temporal::set_warnings(Sql_condition::enum_warning_level trunc_level,
|
||||
*/
|
||||
int Field_temporal_with_date::store_TIME_with_warning(MYSQL_TIME *ltime,
|
||||
const ErrConv *str,
|
||||
int was_cut,
|
||||
int have_smth_to_conv)
|
||||
int was_cut)
|
||||
{
|
||||
Sql_condition::enum_warning_level trunc_level= Sql_condition::WARN_LEVEL_WARN;
|
||||
int ret= 2;
|
||||
int ret;
|
||||
|
||||
ASSERT_COLUMN_MARKED_FOR_WRITE;
|
||||
|
||||
if (was_cut == 0 && have_smth_to_conv == 0) // special case: zero date
|
||||
if (was_cut == 0 && !ltime) // special case: zero date
|
||||
{
|
||||
was_cut= MYSQL_TIME_WARN_OUT_OF_RANGE;
|
||||
store_TIME(const_cast<MYSQL_TIME*>(Datetime().get_mysql_time()));
|
||||
ret= 2;
|
||||
}
|
||||
else if (!have_smth_to_conv)
|
||||
else if (!ltime)
|
||||
{
|
||||
bzero(ltime, sizeof(*ltime));
|
||||
was_cut= MYSQL_TIME_WARN_TRUNCATED;
|
||||
store_TIME(const_cast<MYSQL_TIME*>(Datetime().get_mysql_time()));
|
||||
ret= 1;
|
||||
}
|
||||
else if (!MYSQL_TIME_WARN_HAVE_WARNINGS(was_cut) &&
|
||||
@ -5582,12 +5566,17 @@ int Field_temporal_with_date::store_TIME_with_warning(MYSQL_TIME *ltime,
|
||||
{
|
||||
trunc_level= Sql_condition::WARN_LEVEL_NOTE;
|
||||
was_cut|= MYSQL_TIME_WARN_TRUNCATED;
|
||||
store_TIME(ltime);
|
||||
ret= 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
store_TIME(ltime);
|
||||
ret= was_cut ? 2 : 0;
|
||||
}
|
||||
set_warnings(trunc_level, str, was_cut,
|
||||
type_handler()->mysql_timestamp_type());
|
||||
store_TIME(ltime);
|
||||
return was_cut ? ret : 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -5597,10 +5586,9 @@ int Field_temporal_with_date::store(const char *from, size_t len, CHARSET_INFO *
|
||||
MYSQL_TIME_STATUS status;
|
||||
THD *thd= get_thd();
|
||||
ErrConvString str(from, len, cs);
|
||||
bool func_res= !str_to_datetime(cs, from, len, <ime,
|
||||
sql_mode_for_dates(thd),
|
||||
&status);
|
||||
return store_TIME_with_warning(<ime, &str, status.warnings, func_res);
|
||||
bool rc= str_to_datetime(cs, from, len, <ime, sql_mode_for_dates(thd),
|
||||
&status);
|
||||
return store_TIME_with_warning(rc ? NULL : <ime, &str, status.warnings);
|
||||
}
|
||||
|
||||
|
||||
@ -5611,7 +5599,7 @@ int Field_temporal_with_date::store(double nr)
|
||||
THD *thd= get_thd();
|
||||
ErrConvDouble str(nr);
|
||||
bool rc= Sec6(nr).to_datetime(<ime, sql_mode_for_dates(thd), &error);
|
||||
return store_TIME_with_warning(<ime, &str, error, !rc);
|
||||
return store_TIME_with_warning(rc ? NULL : <ime, &str, error);
|
||||
}
|
||||
|
||||
|
||||
@ -5623,35 +5611,18 @@ int Field_temporal_with_date::store(longlong nr, bool unsigned_val)
|
||||
ErrConvInteger str(nr, unsigned_val);
|
||||
bool rc= Sec6(nr, unsigned_val).to_datetime(<ime, sql_mode_for_dates(thd),
|
||||
&error);
|
||||
return store_TIME_with_warning(<ime, &str, error, !rc);
|
||||
return store_TIME_with_warning(rc ? NULL : <ime, &str, error);
|
||||
}
|
||||
|
||||
|
||||
int Field_temporal_with_date::store_time_dec(const MYSQL_TIME *ltime, uint dec)
|
||||
{
|
||||
int error= 0, have_smth_to_conv= 1;
|
||||
int error;
|
||||
ErrConvTime str(ltime);
|
||||
MYSQL_TIME l_time;
|
||||
|
||||
if (copy_or_convert_to_datetime(get_thd(), ltime, &l_time))
|
||||
{
|
||||
/*
|
||||
Set have_smth_to_conv and error in a way to have
|
||||
store_TIME_with_warning do bzero().
|
||||
*/
|
||||
have_smth_to_conv= false;
|
||||
error= MYSQL_TIME_WARN_OUT_OF_RANGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
We don't perform range checking here since values stored in TIME
|
||||
structure always fit into DATETIME range.
|
||||
*/
|
||||
have_smth_to_conv= !check_date(&l_time, pack_time(&l_time) != 0,
|
||||
sql_mode_for_dates(get_thd()), &error);
|
||||
}
|
||||
return store_TIME_with_warning(&l_time, &str, error, have_smth_to_conv);
|
||||
THD *thd= get_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(const_cast<MYSQL_TIME*>(ltime), &str, error);
|
||||
}
|
||||
|
||||
|
||||
@ -5738,16 +5709,14 @@ Item *Field_temporal::get_equal_const_item_datetime(THD *thd,
|
||||
** Stored as a 3 byte unsigned int
|
||||
****************************************************************************/
|
||||
int Field_time::store_TIME_with_warning(MYSQL_TIME *ltime,
|
||||
const ErrConv *str,
|
||||
int was_cut,
|
||||
int have_smth_to_conv)
|
||||
const ErrConv *str, int was_cut)
|
||||
{
|
||||
ASSERT_COLUMN_MARKED_FOR_WRITE;
|
||||
|
||||
if (!have_smth_to_conv)
|
||||
if (!ltime)
|
||||
{
|
||||
bzero(ltime, sizeof(*ltime));
|
||||
store_TIME(ltime);
|
||||
Datetime tmp;
|
||||
store_TIME(const_cast<MYSQL_TIME*>(tmp.get_mysql_time()));
|
||||
set_warnings(Sql_condition::WARN_LEVEL_WARN, str, MYSQL_TIME_WARN_TRUNCATED);
|
||||
return 1;
|
||||
}
|
||||
@ -5786,54 +5755,19 @@ 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);
|
||||
bool have_smth_to_conv=
|
||||
!str_to_time(cs, from, len, <ime, sql_mode_for_dates(get_thd()),
|
||||
&status);
|
||||
|
||||
return store_TIME_with_warning(<ime, &str,
|
||||
status.warnings, have_smth_to_conv);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
subtract a given number of days from DATETIME, return TIME
|
||||
|
||||
optimized version of calc_time_diff()
|
||||
|
||||
@note it might generate TIME values outside of the valid TIME range!
|
||||
*/
|
||||
static void calc_datetime_days_diff(MYSQL_TIME *ltime, long days)
|
||||
{
|
||||
long daydiff= calc_daynr(ltime->year, ltime->month, ltime->day) - days;
|
||||
ltime->year= ltime->month= 0;
|
||||
if (daydiff >=0 )
|
||||
{
|
||||
ltime->day= daydiff;
|
||||
ltime->time_type= MYSQL_TIMESTAMP_TIME;
|
||||
}
|
||||
else
|
||||
{
|
||||
longlong timediff= ((((daydiff * 24LL +
|
||||
ltime->hour) * 60LL +
|
||||
ltime->minute) * 60LL +
|
||||
ltime->second) * 1000000LL +
|
||||
ltime->second_part);
|
||||
unpack_time(timediff, ltime, MYSQL_TIMESTAMP_TIME);
|
||||
}
|
||||
bool rc= str_to_time(cs, from, len, <ime, sql_mode_for_dates(get_thd()),
|
||||
&status);
|
||||
return store_TIME_with_warning(rc ? NULL : <ime, &str, status.warnings);
|
||||
}
|
||||
|
||||
|
||||
int Field_time::store_time_dec(const MYSQL_TIME *ltime, uint dec)
|
||||
{
|
||||
MYSQL_TIME l_time= *ltime;
|
||||
ErrConvTime str(ltime);
|
||||
int was_cut= 0;
|
||||
|
||||
if (curdays && l_time.time_type != MYSQL_TIMESTAMP_TIME)
|
||||
calc_datetime_days_diff(&l_time, curdays);
|
||||
|
||||
int have_smth_to_conv= !check_time_range(&l_time, decimals(), &was_cut);
|
||||
return store_TIME_with_warning(&l_time, &str, was_cut, have_smth_to_conv);
|
||||
int warn;
|
||||
Time tm(&warn, ltime, curdays);
|
||||
ltime= tm.is_valid_time() ? tm.get_mysql_time() : NULL;
|
||||
return store_TIME_with_warning(const_cast<MYSQL_TIME *>(ltime), &str, warn);
|
||||
}
|
||||
|
||||
|
||||
@ -5843,7 +5777,7 @@ int Field_time::store(double nr)
|
||||
ErrConvDouble str(nr);
|
||||
int was_cut;
|
||||
bool rc= Sec6(nr).to_time(<ime, &was_cut);
|
||||
return store_TIME_with_warning(<ime, &str, was_cut, !rc);
|
||||
return store_TIME_with_warning(rc ? NULL : <ime, &str, was_cut);
|
||||
}
|
||||
|
||||
|
||||
@ -5853,7 +5787,7 @@ int Field_time::store(longlong nr, bool unsigned_val)
|
||||
ErrConvInteger str(nr, unsigned_val);
|
||||
int was_cut;
|
||||
bool rc= Sec6(nr, unsigned_val).to_time(<ime, &was_cut);
|
||||
return store_TIME_with_warning(<ime, &str, was_cut, !rc);
|
||||
return store_TIME_with_warning(rc ? NULL : <ime, &str, was_cut);
|
||||
}
|
||||
|
||||
|
||||
@ -6012,7 +5946,7 @@ int Field_time::store_decimal(const my_decimal *d)
|
||||
MYSQL_TIME ltime;
|
||||
int was_cut;
|
||||
bool rc= Sec6(d).to_time(<ime, &was_cut);
|
||||
return store_TIME_with_warning(<ime, &str, was_cut, !rc);
|
||||
return store_TIME_with_warning(rc ? NULL : <ime, &str, was_cut);
|
||||
}
|
||||
|
||||
|
||||
@ -6735,7 +6669,7 @@ int Field_temporal_with_date::store_decimal(const my_decimal *d)
|
||||
THD *thd= get_thd();
|
||||
ErrConvDecimal str(d);
|
||||
bool rc= Sec6(d).to_datetime(<ime, sql_mode_for_dates(thd), &error);
|
||||
return store_TIME_with_warning(<ime, &str, error, !rc);
|
||||
return store_TIME_with_warning(rc ? NULL : <ime, &str, error);
|
||||
}
|
||||
|
||||
bool Field_datetime_with_dec::send_binary(Protocol *protocol)
|
||||
|
@ -2661,7 +2661,7 @@ public:
|
||||
class Field_temporal_with_date: public Field_temporal {
|
||||
protected:
|
||||
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 bool get_TIME(MYSQL_TIME *ltime, const uchar *pos,
|
||||
ulonglong fuzzydate) const = 0;
|
||||
@ -2694,8 +2694,7 @@ public:
|
||||
class Field_timestamp :public Field_temporal {
|
||||
protected:
|
||||
sql_mode_t sql_mode_for_timestamp(THD *thd) const;
|
||||
int store_TIME_with_warning(THD *, MYSQL_TIME *, const ErrConv *,
|
||||
int warnings, bool have_smth_to_conv);
|
||||
int store_TIME_with_warning(THD *, MYSQL_TIME *, const ErrConv *, int warn);
|
||||
public:
|
||||
Field_timestamp(uchar *ptr_arg, uint32 len_arg,
|
||||
uchar *null_ptr_arg, uchar null_bit_arg,
|
||||
@ -3020,8 +3019,7 @@ class Field_time :public Field_temporal {
|
||||
long curdays;
|
||||
protected:
|
||||
virtual void store_TIME(const MYSQL_TIME *ltime);
|
||||
int store_TIME_with_warning(MYSQL_TIME *ltime, const ErrConv *str,
|
||||
int was_cut, int have_smth_to_conv);
|
||||
int store_TIME_with_warning(MYSQL_TIME *ltime, const ErrConv *str, int warn);
|
||||
void set_warnings(Sql_condition::enum_warning_level level,
|
||||
const ErrConv *str, int was_cut)
|
||||
{
|
||||
|
158
sql/sql_type.cc
158
sql/sql_type.cc
@ -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)
|
||||
{
|
||||
flags&= ~TIME_TIME_ONLY;
|
||||
@ -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 res= 0;
|
||||
|
@ -460,6 +460,11 @@ protected:
|
||||
return negate ? -d : d;
|
||||
}
|
||||
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:
|
||||
};
|
||||
|
||||
@ -574,7 +579,23 @@ private:
|
||||
second <= TIME_MAX_SECOND &&
|
||||
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.
|
||||
Before this call, "this" must be a valid DATE or DATETIME value,
|
||||
@ -635,11 +656,23 @@ private:
|
||||
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);
|
||||
public:
|
||||
Time() { time_type= MYSQL_TIMESTAMP_NONE; }
|
||||
Time(Item *item) { make_from_item(item, Options()); }
|
||||
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()
|
||||
{ return TIME_TIME_ONLY | TIME_INVALID_DATES; }
|
||||
static sql_mode_t comparison_flags_for_get_date()
|
||||
@ -744,8 +777,13 @@ public:
|
||||
class Temporal_with_date: protected Temporal
|
||||
{
|
||||
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);
|
||||
Temporal_with_date()
|
||||
{
|
||||
time_type= MYSQL_TIMESTAMP_NONE;
|
||||
}
|
||||
Temporal_with_date(THD *thd, Item *item, sql_mode_t flags)
|
||||
{
|
||||
make_from_item(thd, item, flags);
|
||||
@ -878,6 +916,10 @@ class Datetime: public Temporal_with_date
|
||||
DBUG_ASSERT(time_type == MYSQL_TIMESTAMP_DATETIME);
|
||||
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:
|
||||
Datetime(THD *thd, Item *item, sql_mode_t flags)
|
||||
:Temporal_with_date(thd, item, flags)
|
||||
@ -900,6 +942,11 @@ public:
|
||||
date_to_datetime(this);
|
||||
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
|
||||
{
|
||||
/*
|
||||
@ -974,6 +1021,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Flags for collation aggregation modes, used in TDCollation::agg():
|
||||
|
||||
|
Reference in New Issue
Block a user