Skip to content

Commit 2fe51a6

Browse files
committed
MDEV-17175 Change Time/Datetime constructors to return warnings in MYSQL_TIME_STATUS
1 parent 5567a8c commit 2fe51a6

File tree

5 files changed

+99
-74
lines changed

5 files changed

+99
-74
lines changed

sql/field.cc

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5093,9 +5093,9 @@ int Field_timestamp::store(const char *from,size_t len,CHARSET_INFO *cs)
50935093
{
50945094
ErrConvString str(from, len, cs);
50955095
THD *thd= get_thd();
5096-
int error;
5097-
Datetime dt(&error, from, len, cs, sql_mode_for_timestamp(thd));
5098-
return store_TIME_with_warning(thd, &dt, &str, error);
5096+
MYSQL_TIME_STATUS st;
5097+
Datetime dt(&st, from, len, cs, sql_mode_for_timestamp(thd));
5098+
return store_TIME_with_warning(thd, &dt, &str, st.warnings);
50995099
}
51005100

51015101

@@ -5577,10 +5577,10 @@ int Field_temporal_with_date::store_TIME_with_warning(const Datetime *dt,
55775577

55785578
int Field_temporal_with_date::store(const char *from, size_t len, CHARSET_INFO *cs)
55795579
{
5580-
int error;
5580+
MYSQL_TIME_STATUS st;
55815581
ErrConvString str(from, len, cs);
5582-
Datetime dt(&error, from, len, cs, sql_mode_for_dates(get_thd()));
5583-
return store_TIME_with_warning(&dt, &str, error);
5582+
Datetime dt(&st, from, len, cs, sql_mode_for_dates(get_thd()));
5583+
return store_TIME_with_warning(&dt, &str, st.warnings);
55845584
}
55855585

55865586
int Field_temporal_with_date::store(double nr)
@@ -5731,9 +5731,9 @@ void Field_time::store_TIME(const MYSQL_TIME *ltime)
57315731
int Field_time::store(const char *from,size_t len,CHARSET_INFO *cs)
57325732
{
57335733
ErrConvString str(from, len, cs);
5734-
int error;
5735-
Time tm(&error, from, len, cs, sql_mode_for_dates(get_thd()));
5736-
return store_TIME_with_warning(&tm, &str, error);
5734+
MYSQL_TIME_STATUS st;
5735+
Time tm(&st, from, len, cs, sql_mode_for_dates(get_thd()));
5736+
return store_TIME_with_warning(&tm, &str, st.warnings);
57375737
}
57385738

57395739

sql/sql_time.cc

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -351,33 +351,43 @@ to_ascii(CHARSET_INFO *cs,
351351
}
352352

353353

354-
/* Character set-aware version of str_to_time() */
355-
bool
356-
str_to_time(CHARSET_INFO *cs, const char *str, size_t length,
357-
MYSQL_TIME *l_time, ulonglong fuzzydate, MYSQL_TIME_STATUS *status)
354+
class TemporalAsciiBuffer: public LEX_CSTRING
358355
{
359356
char cnv[32];
360-
if ((cs->state & MY_CS_NONASCII) != 0)
357+
public:
358+
TemporalAsciiBuffer(const char *str, size_t length, CHARSET_INFO *cs)
361359
{
362-
length= to_ascii(cs, str, length, cnv, sizeof(cnv));
363-
str= cnv;
360+
if ((cs->state & MY_CS_NONASCII) != 0)
361+
{
362+
LEX_CSTRING::str= cnv;
363+
LEX_CSTRING::length= to_ascii(cs, str, length, cnv, sizeof(cnv));
364+
}
365+
else
366+
{
367+
LEX_CSTRING::str= str;
368+
LEX_CSTRING::length= length;
369+
}
364370
}
365-
return str_to_time(str, length, l_time, fuzzydate, status);
371+
};
372+
373+
374+
/* Character set-aware version of str_to_time() */
375+
bool Temporal::str_to_time(MYSQL_TIME_STATUS *status,
376+
const char *str, size_t length, CHARSET_INFO *cs,
377+
sql_mode_t fuzzydate)
378+
{
379+
TemporalAsciiBuffer tmp(str, length, cs);
380+
return ::str_to_time(tmp.str, tmp.length, this, fuzzydate, status);
366381
}
367382

368383

369384
/* Character set-aware version of str_to_datetime() */
370-
bool str_to_datetime(CHARSET_INFO *cs, const char *str, size_t length,
371-
MYSQL_TIME *l_time, ulonglong flags,
372-
MYSQL_TIME_STATUS *status)
385+
bool Temporal::str_to_datetime(MYSQL_TIME_STATUS *status,
386+
const char *str, size_t length, CHARSET_INFO *cs,
387+
sql_mode_t flags)
373388
{
374-
char cnv[32];
375-
if ((cs->state & MY_CS_NONASCII) != 0)
376-
{
377-
length= to_ascii(cs, str, length, cnv, sizeof(cnv));
378-
str= cnv;
379-
}
380-
return str_to_datetime(str, length, l_time, flags, status);
389+
TemporalAsciiBuffer tmp(str, length, cs);
390+
return ::str_to_datetime(tmp.str, tmp.length, this, flags, status);
381391
}
382392

383393

@@ -396,7 +406,8 @@ str_to_datetime_with_warn(CHARSET_INFO *cs,
396406
{
397407
MYSQL_TIME_STATUS status;
398408
THD *thd= current_thd;
399-
bool ret_val= str_to_datetime(cs, str, length, l_time, flags, &status);
409+
TemporalAsciiBuffer tmp(str, length, cs);
410+
bool ret_val= str_to_datetime(tmp.str, tmp.length, l_time, flags, &status);
400411
if (ret_val || status.warnings)
401412
{
402413
const ErrConvString err(str, length, &my_charset_bin);

sql/sql_time.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -126,15 +126,6 @@ int calc_weekday(long daynr,bool sunday_first_day_of_week);
126126
bool parse_date_time_format(timestamp_type format_type,
127127
const char *format, uint format_length,
128128
DATE_TIME_FORMAT *date_time_format);
129-
/* Character set-aware version of str_to_time() */
130-
bool str_to_time(CHARSET_INFO *cs, const char *str,size_t length,
131-
MYSQL_TIME *l_time, ulonglong fuzzydate,
132-
MYSQL_TIME_STATUS *status);
133-
/* Character set-aware version of str_to_datetime() */
134-
bool str_to_datetime(CHARSET_INFO *cs,
135-
const char *str, size_t length,
136-
MYSQL_TIME *l_time, ulonglong flags,
137-
MYSQL_TIME_STATUS *status);
138129

139130
/* convenience wrapper */
140131
inline bool parse_date_time_format(timestamp_type format_type,

sql/sql_type.cc

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5489,17 +5489,19 @@ uint Type_handler::Item_datetime_precision(Item *item) const
54895489
uint Type_handler_string_result::Item_temporal_precision(Item *item,
54905490
bool is_time) const
54915491
{
5492-
MYSQL_TIME ltime;
54935492
StringBuffer<64> buf;
54945493
String *tmp;
54955494
MYSQL_TIME_STATUS status;
54965495
DBUG_ASSERT(item->is_fixed());
54975496
if ((tmp= item->val_str(&buf)) &&
5498-
!(is_time ?
5499-
str_to_time(tmp->charset(), tmp->ptr(), tmp->length(),
5500-
&ltime, TIME_TIME_ONLY, &status) :
5501-
str_to_datetime(tmp->charset(), tmp->ptr(), tmp->length(),
5502-
&ltime, TIME_FUZZY_DATES, &status)))
5497+
(is_time ?
5498+
Time(&status, tmp->ptr(), tmp->length(), tmp->charset(),
5499+
Time::Options(TIME_TIME_ONLY,
5500+
Time::DATETIME_TO_TIME_YYYYMMDD_TRUNCATE)).
5501+
is_valid_time() :
5502+
Datetime(&status, tmp->ptr(), tmp->length(), tmp->charset(),
5503+
TIME_FUZZY_DATES).
5504+
is_valid_datetime()))
55035505
return MY_MIN(status.precision, TIME_SECOND_PART_DIGITS);
55045506
return MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS);
55055507
}
@@ -7208,7 +7210,7 @@ static bool have_important_literal_warnings(const MYSQL_TIME_STATUS *status)
72087210

72097211
static void literal_warn(THD *thd, const Item *item,
72107212
const char *str, size_t length, CHARSET_INFO *cs,
7211-
const MYSQL_TIME *ltime,
7213+
timestamp_type time_type,
72127214
const MYSQL_TIME_STATUS *st,
72137215
const char *typestr, bool send_error)
72147216
{
@@ -7219,7 +7221,7 @@ static void literal_warn(THD *thd, const Item *item,
72197221
ErrConvString err(str, length, cs);
72207222
make_truncated_value_warning(thd,
72217223
Sql_condition::time_warn_level(st->warnings),
7222-
&err, ltime->time_type, 0);
7224+
&err, time_type, 0);
72237225
}
72247226
}
72257227
else if (send_error)
@@ -7238,13 +7240,14 @@ Type_handler_date_common::create_literal_item(THD *thd,
72387240
bool send_error) const
72397241
{
72407242
MYSQL_TIME_STATUS st;
7241-
MYSQL_TIME ltime;
72427243
Item_literal *item= NULL;
7243-
sql_mode_t flags= sql_mode_for_dates(thd);
7244-
if (!str_to_datetime(cs, str, length, &ltime, flags, &st) &&
7245-
ltime.time_type == MYSQL_TIMESTAMP_DATE && !st.warnings)
7246-
item= new (thd->mem_root) Item_date_literal(thd, &ltime);
7247-
literal_warn(thd, item, str, length, cs, &ltime, &st, "DATE", send_error);
7244+
Temporal_hybrid tmp(&st, str, length, cs, sql_mode_for_dates(thd));
7245+
if (tmp.is_valid_temporal() &&
7246+
tmp.get_mysql_time()->time_type == MYSQL_TIMESTAMP_DATE &&
7247+
!have_important_literal_warnings(&st))
7248+
item= new (thd->mem_root) Item_date_literal(thd, tmp.get_mysql_time());
7249+
literal_warn(thd, item, str, length, cs, MYSQL_TIMESTAMP_DATE,
7250+
&st, "DATE", send_error);
72487251
return item;
72497252
}
72507253

@@ -7257,14 +7260,15 @@ Type_handler_temporal_with_date::create_literal_item(THD *thd,
72577260
bool send_error) const
72587261
{
72597262
MYSQL_TIME_STATUS st;
7260-
MYSQL_TIME ltime;
72617263
Item_literal *item= NULL;
7262-
sql_mode_t flags= sql_mode_for_dates(thd);
7263-
if (!str_to_datetime(cs, str, length, &ltime, flags, &st) &&
7264-
ltime.time_type == MYSQL_TIMESTAMP_DATETIME &&
7264+
Temporal_hybrid tmp(&st, str, length, cs, sql_mode_for_dates(thd));
7265+
if (tmp.is_valid_temporal() &&
7266+
tmp.get_mysql_time()->time_type == MYSQL_TIMESTAMP_DATETIME &&
72657267
!have_important_literal_warnings(&st))
7266-
item= new (thd->mem_root) Item_datetime_literal(thd, &ltime, st.precision);
7267-
literal_warn(thd, item, str, length, cs, &ltime, &st, "DATETIME", send_error);
7268+
item= new (thd->mem_root) Item_datetime_literal(thd, tmp.get_mysql_time(),
7269+
st.precision);
7270+
literal_warn(thd, item, str, length, cs, MYSQL_TIMESTAMP_DATETIME,
7271+
&st, "DATETIME", send_error);
72687272
return item;
72697273
}
72707274

@@ -7277,12 +7281,14 @@ Type_handler_time_common::create_literal_item(THD *thd,
72777281
bool send_error) const
72787282
{
72797283
MYSQL_TIME_STATUS st;
7280-
MYSQL_TIME ltime;
72817284
Item_literal *item= NULL;
7282-
if (!str_to_time(cs, str, length, &ltime, 0, &st) &&
7283-
ltime.time_type == MYSQL_TIMESTAMP_TIME &&
7285+
Time::Options opt(TIME_TIME_ONLY, Time::DATETIME_TO_TIME_DISALLOW);
7286+
Time tmp(&st, str, length, cs, opt);
7287+
if (tmp.is_valid_time() &&
72847288
!have_important_literal_warnings(&st))
7285-
item= new (thd->mem_root) Item_time_literal(thd, &ltime, st.precision);
7286-
literal_warn(thd, item, str, length, cs, &ltime, &st, "TIME", send_error);
7289+
item= new (thd->mem_root) Item_time_literal(thd, tmp.get_mysql_time(),
7290+
st.precision);
7291+
literal_warn(thd, item, str, length, cs, MYSQL_TIMESTAMP_TIME,
7292+
&st, "TIME", send_error);
72877293
return item;
72887294
}

sql/sql_type.h

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -446,12 +446,13 @@ class VYear_op: public Year_null
446446

447447
class Temporal: protected MYSQL_TIME
448448
{
449-
protected:
449+
public:
450450
bool is_valid_temporal() const
451451
{
452452
DBUG_ASSERT(time_type != MYSQL_TIMESTAMP_ERROR);
453453
return time_type != MYSQL_TIMESTAMP_NONE;
454454
}
455+
protected:
455456
my_decimal *bad_to_decimal(my_decimal *to) const;
456457
my_decimal *to_decimal(my_decimal *to) const;
457458
static double to_double(bool negate, ulonglong num, ulong frac)
@@ -465,6 +466,10 @@ class Temporal: protected MYSQL_TIME
465466
*warn= MYSQL_TIME_WARN_OUT_OF_RANGE;
466467
time_type= MYSQL_TIMESTAMP_NONE;
467468
}
469+
bool str_to_time(MYSQL_TIME_STATUS *st, const char *str, size_t length,
470+
CHARSET_INFO *cs, sql_mode_t fuzzydate);
471+
bool str_to_datetime(MYSQL_TIME_STATUS *st, const char *str, size_t length,
472+
CHARSET_INFO *cs, sql_mode_t fuzzydate);
468473
public:
469474
long fraction_remainder(uint dec) const
470475
{
@@ -483,6 +488,12 @@ class Temporal_hybrid: public Temporal
483488
public:
484489
Temporal_hybrid(THD *thd, Item *item);
485490
Temporal_hybrid(Item *item) { *this= Temporal_hybrid(current_thd, item); }
491+
Temporal_hybrid(MYSQL_TIME_STATUS *st, const char *str, size_t length,
492+
CHARSET_INFO *cs, sql_mode_t fuzzydate)
493+
{
494+
if (str_to_datetime(st, str, length, cs, fuzzydate))
495+
time_type= MYSQL_TIMESTAMP_NONE;
496+
}
486497
longlong to_longlong() const
487498
{
488499
if (!is_valid_temporal())
@@ -507,6 +518,11 @@ class Temporal_hybrid: public Temporal
507518
str->length(my_TIME_to_str(this, const_cast<char*>(str->ptr()), dec));
508519
return str;
509520
}
521+
const MYSQL_TIME *get_mysql_time() const
522+
{
523+
DBUG_ASSERT(is_valid_temporal());
524+
return this;
525+
}
510526
};
511527

512528

@@ -533,6 +549,7 @@ class Time: public Temporal
533549
public:
534550
enum datetime_to_time_mode_t
535551
{
552+
DATETIME_TO_TIME_DISALLOW,
536553
DATETIME_TO_TIME_YYYYMMDD_000000DD_MIX_TO_HOURS,
537554
DATETIME_TO_TIME_YYYYMMDD_TRUNCATE,
538555
DATETIME_TO_TIME_YYYYMMDD_00000000_ONLY,
@@ -674,6 +691,8 @@ class Time: public Temporal
674691
DATETIME_TO_TIME_YYYYMMDD_00000000_ONLY &&
675692
(year || month || day))
676693
make_from_out_of_range(warn);
694+
else if (opt.datetime_to_time_mode() == DATETIME_TO_TIME_DISALLOW)
695+
make_from_out_of_range(warn);
677696
else
678697
valid_datetime_to_valid_time(warn, opt);
679698
break;
@@ -729,15 +748,13 @@ class Time: public Temporal
729748
make_from_item(&warn, item, opt);
730749
}
731750
Time(int *warn, const MYSQL_TIME *from, long curdays);
732-
Time(int *warn, const char *str, size_t len, CHARSET_INFO *cs,
751+
Time(MYSQL_TIME_STATUS *status, const char *str, size_t len, CHARSET_INFO *cs,
733752
const Options opt)
734753
{
735-
MYSQL_TIME_STATUS status;
736-
if (str_to_time(cs, str, len, this, opt.get_date_flags(), &status))
754+
if (str_to_time(status, str, len, cs, opt.get_date_flags()))
737755
time_type= MYSQL_TIMESTAMP_NONE;
738756
// The below call will optionally add notes to already collected warnings:
739-
xxx_to_time_result_to_valid_value(&status.warnings, opt);
740-
*warn= status.warnings;
757+
xxx_to_time_result_to_valid_value(&status->warnings, opt);
741758
}
742759
Time(int *warn, const Sec6 &nr, const Options opt)
743760
{
@@ -885,14 +902,13 @@ class Temporal_with_date: public Temporal
885902
if (nr.to_datetime(this, flags, warn))
886903
time_type= MYSQL_TIMESTAMP_NONE;
887904
}
888-
Temporal_with_date(int *warn, const char *str, size_t len, CHARSET_INFO *cs,
905+
Temporal_with_date(MYSQL_TIME_STATUS *status,
906+
const char *str, size_t len, CHARSET_INFO *cs,
889907
sql_mode_t flags)
890908
{
891909
DBUG_ASSERT((flags & TIME_TIME_ONLY) == 0);
892-
MYSQL_TIME_STATUS status;
893-
if (str_to_datetime(cs, str, len, this, flags, &status))
910+
if (str_to_datetime(status, str, len, cs, flags))
894911
time_type= MYSQL_TIMESTAMP_NONE;
895-
*warn= status.warnings;
896912
}
897913
public:
898914
bool check_date_with_warn(ulonglong flags)
@@ -1051,9 +1067,10 @@ class Datetime: public Temporal_with_date
10511067
{
10521068
set_zero_time(this, MYSQL_TIMESTAMP_DATETIME);
10531069
}
1054-
Datetime(int *warn, const char *str, size_t len, CHARSET_INFO *cs,
1070+
Datetime(MYSQL_TIME_STATUS *status,
1071+
const char *str, size_t len, CHARSET_INFO *cs,
10551072
sql_mode_t flags)
1056-
:Temporal_with_date(warn, str, len, cs, flags)
1073+
:Temporal_with_date(status, str, len, cs, flags)
10571074
{
10581075
date_to_datetime_if_needed();
10591076
DBUG_ASSERT(is_valid_value_slow());

0 commit comments

Comments
 (0)