1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Merge branch 'bb-10.2-ext' into 10.3

This commit is contained in:
Sergei Golubchik
2018-02-23 08:43:34 +01:00
63 changed files with 1137 additions and 517 deletions

View File

@ -95,6 +95,47 @@ struct SORT_FIELD_ATTR;
*/
class Time: private MYSQL_TIME
{
public:
enum datetime_to_time_mode_t
{
DATETIME_TO_TIME_YYYYMMDD_000000DD_MIX_TO_HOURS,
DATETIME_TO_TIME_YYYYMMDD_TRUNCATE
};
class Options
{
sql_mode_t m_get_date_flags;
datetime_to_time_mode_t m_datetime_to_time_mode;
public:
Options()
:m_get_date_flags(flags_for_get_date()),
m_datetime_to_time_mode(DATETIME_TO_TIME_YYYYMMDD_000000DD_MIX_TO_HOURS)
{ }
Options(sql_mode_t flags)
:m_get_date_flags(flags),
m_datetime_to_time_mode(DATETIME_TO_TIME_YYYYMMDD_000000DD_MIX_TO_HOURS)
{ }
Options(sql_mode_t flags, datetime_to_time_mode_t dtmode)
:m_get_date_flags(flags),
m_datetime_to_time_mode(dtmode)
{ }
sql_mode_t get_date_flags() const
{ return m_get_date_flags; }
datetime_to_time_mode_t datetime_to_time_mode() const
{ return m_datetime_to_time_mode; }
};
/*
CAST(AS TIME) historically does not mix days to hours.
This is different comparing to how implicit conversion
in Field::store_time_dec() works (e.g. on INSERT).
*/
class Options_for_cast: public Options
{
public:
Options_for_cast()
:Options(flags_for_get_date(), DATETIME_TO_TIME_YYYYMMDD_TRUNCATE)
{ }
};
private:
bool is_valid_value_slow() const
{
return time_type == MYSQL_TIMESTAMP_NONE || is_valid_time_slow();
@ -114,7 +155,7 @@ class Time: private MYSQL_TIME
e.g. returned from Item::get_date().
After this call, "this" is a valid TIME value.
*/
void valid_datetime_to_valid_time()
void valid_datetime_to_valid_time(const Options opt)
{
DBUG_ASSERT(time_type == MYSQL_TIMESTAMP_DATE ||
time_type == MYSQL_TIMESTAMP_DATETIME);
@ -124,7 +165,9 @@ class Time: private MYSQL_TIME
*/
DBUG_ASSERT(day < 32);
DBUG_ASSERT(hour < 24);
if (year == 0 && month == 0)
if (year == 0 && month == 0 &&
opt.datetime_to_time_mode() ==
DATETIME_TO_TIME_YYYYMMDD_000000DD_MIX_TO_HOURS)
{
/*
The maximum hour value after mixing days will be 31*24+23=767,
@ -149,12 +192,12 @@ class Time: private MYSQL_TIME
- either a valid TIME (within the supported TIME range),
- or MYSQL_TIMESTAMP_NONE
*/
void valid_MYSQL_TIME_to_valid_value()
void valid_MYSQL_TIME_to_valid_value(const Options opt)
{
switch (time_type) {
case MYSQL_TIMESTAMP_DATE:
case MYSQL_TIMESTAMP_DATETIME:
valid_datetime_to_valid_time();
valid_datetime_to_valid_time(opt);
break;
case MYSQL_TIMESTAMP_NONE:
break;
@ -166,19 +209,35 @@ class Time: private MYSQL_TIME
break;
}
}
void make_from_item(class Item *item);
void make_from_item(class Item *item, const Options opt);
public:
Time() { time_type= MYSQL_TIMESTAMP_NONE; }
Time(Item *item) { make_from_item(item); }
Time(Item *item) { make_from_item(item, Options()); }
Time(Item *item, const Options opt) { make_from_item(item, opt); }
static sql_mode_t flags_for_get_date()
{ return TIME_TIME_ONLY | TIME_INVALID_DATES; }
static sql_mode_t comparison_flags_for_get_date()
{ return TIME_TIME_ONLY | TIME_INVALID_DATES | TIME_FUZZY_DATES; }
bool is_valid_time() const
{
DBUG_ASSERT(is_valid_value_slow());
return time_type == MYSQL_TIMESTAMP_TIME;
}
void copy_to_mysql_time(MYSQL_TIME *ltime) const
const MYSQL_TIME *get_mysql_time() const
{
DBUG_ASSERT(is_valid_time_slow());
return this;
}
bool copy_to_mysql_time(MYSQL_TIME *ltime) const
{
if (time_type == MYSQL_TIMESTAMP_NONE)
{
ltime->time_type= MYSQL_TIMESTAMP_NONE;
return true;
}
DBUG_ASSERT(is_valid_time_slow());
*ltime= *this;
return false;
}
int cmp(const Time *other) const
{
@ -192,9 +251,175 @@ public:
return 1;
return 0;
}
longlong to_seconds_abs() const
{
DBUG_ASSERT(is_valid_time_slow());
return hour * 3600L + minute * 60 + second;
}
longlong to_seconds() const
{
return neg ? -to_seconds_abs() : to_seconds_abs();
}
};
/**
Class Temporal_with_date is designed to store valid DATE or DATETIME values.
See also class Time.
1. Valid value:
a. MYSQL_TIMESTAMP_{DATE|DATETIME} - a valid DATE or DATETIME value
b. MYSQL_TIMESTAMP_NONE - an undefined value
2. Invalid value (internally only):
a. MYSQL_TIMESTAMP_{DATE|DATETIME} - a DATE or DATETIME value, but with
MYSQL_TIME members outside of the
valid/supported range
b. MYSQL_TIMESTAMP_TIME - a TIME value
c. MYSQL_TIMESTAMP_ERROR - error
Temporarily is allowed to have an invalid value, but only internally,
during initialization time. All constructors and modification methods must
leave the value as described above (see "Valid value").
Derives from MYSQL_TIME using "protected" inheritance to make sure
it is accessed externally only in the valid state.
*/
class Temporal_with_date: protected MYSQL_TIME
{
protected:
void make_from_item(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);
}
};
/**
Class Date is designed to store valid DATE values.
All constructors and modification methods leave instances
of this class in one of the following valid states:
a. MYSQL_TIMESTAMP_DATE - a DATE with all MYSQL_TIME members properly set
b. MYSQL_TIMESTAMP_NONE - an undefined value.
Other MYSQL_TIMESTAMP_XXX are not possible.
MYSQL_TIMESTAMP_DATE with MYSQL_TIME members improperly set is not possible.
*/
class Date: public Temporal_with_date
{
bool is_valid_value_slow() const
{
return time_type == MYSQL_TIMESTAMP_NONE || is_valid_date_slow();
}
bool is_valid_date_slow() const
{
DBUG_ASSERT(time_type == MYSQL_TIMESTAMP_DATE);
return !check_datetime_range(this);
}
public:
Date(THD *thd, Item *item, sql_mode_t flags)
:Temporal_with_date(thd, item, flags)
{
if (time_type == MYSQL_TIMESTAMP_DATETIME)
datetime_to_date(this);
DBUG_ASSERT(is_valid_value_slow());
}
Date(const Temporal_with_date *d)
:Temporal_with_date(*d)
{
datetime_to_date(this);
DBUG_ASSERT(is_valid_date_slow());
}
bool is_valid_date() const
{
DBUG_ASSERT(is_valid_value_slow());
return time_type == MYSQL_TIMESTAMP_DATE;
}
const MYSQL_TIME *get_mysql_time() const
{
DBUG_ASSERT(is_valid_date_slow());
return this;
}
};
/**
Class Datetime is designed to store valid DATETIME values.
All constructors and modification methods leave instances
of this class in one of the following valid states:
a. MYSQL_TIMESTAMP_DATETIME - a DATETIME with all members properly set
b. MYSQL_TIMESTAMP_NONE - an undefined value.
Other MYSQL_TIMESTAMP_XXX are not possible.
MYSQL_TIMESTAMP_DATETIME with MYSQL_TIME members
improperly set is not possible.
*/
class Datetime: public Temporal_with_date
{
bool is_valid_value_slow() const
{
return time_type == MYSQL_TIMESTAMP_NONE || is_valid_datetime_slow();
}
bool is_valid_datetime_slow() const
{
DBUG_ASSERT(time_type == MYSQL_TIMESTAMP_DATETIME);
return !check_datetime_range(this);
}
public:
Datetime(THD *thd, Item *item, sql_mode_t flags)
:Temporal_with_date(thd, item, flags)
{
if (time_type == MYSQL_TIMESTAMP_DATE)
date_to_datetime(this);
DBUG_ASSERT(is_valid_value_slow());
}
bool is_valid_datetime() const
{
/*
Here we quickly check for the type only.
If the type is valid, the rest of value must also be valid.
*/
DBUG_ASSERT(is_valid_value_slow());
return time_type == MYSQL_TIMESTAMP_DATETIME;
}
bool hhmmssff_is_zero() const
{
DBUG_ASSERT(is_valid_datetime_slow());
return hour == 0 && minute == 0 && second == 0 && second_part == 0;
}
const MYSQL_TIME *get_mysql_time() const
{
DBUG_ASSERT(is_valid_datetime_slow());
return this;
}
bool copy_to_mysql_time(MYSQL_TIME *ltime) const
{
if (time_type == MYSQL_TIMESTAMP_NONE)
{
ltime->time_type= MYSQL_TIMESTAMP_NONE;
return true;
}
DBUG_ASSERT(is_valid_datetime_slow());
*ltime= *this;
return false;
}
/**
Copy without data loss, with an optional DATETIME to DATE conversion.
If the value of the "type" argument is MYSQL_TIMESTAMP_DATE,
then "this" must be a datetime with a zero hhmmssff part.
*/
bool copy_to_mysql_time(MYSQL_TIME *ltime, timestamp_type type)
{
DBUG_ASSERT(type == MYSQL_TIMESTAMP_DATE ||
type == MYSQL_TIMESTAMP_DATETIME);
if (copy_to_mysql_time(ltime))
return true;
DBUG_ASSERT(type != MYSQL_TIMESTAMP_DATE || hhmmssff_is_zero());
ltime->time_type= type;
return false;
}
};
/*
Flags for collation aggregation modes, used in TDCollation::agg():
@ -2234,6 +2459,18 @@ public:
Type_handler_hybrid_field_type *,
Type_all_attributes *atrr,
Item **items, uint nitems) const;
String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
String *) const;
double Item_func_hybrid_field_type_val_real(Item_func_hybrid_field_type *)
const;
longlong Item_func_hybrid_field_type_val_int(Item_func_hybrid_field_type *)
const;
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(Item_func_hybrid_field_type *,
MYSQL_TIME *,
ulonglong fuzzydate) const;
bool Item_func_min_max_get_date(Item_func_min_max*,
MYSQL_TIME *, ulonglong fuzzydate) const;
Item *make_const_item_for_comparison(THD *, Item *src, const Item *cmp) const;