More windows changes for 32 bit unsigned timestamp:

MDEV-32188 make TIMESTAMP use whole 32-bit unsigned range

- Changed usage of timeval to my_timeval as the timeval parts on windows
  are 32-bit long, which causes some compiler issues on windows.
This commit is contained in:
Monty 2023-09-18 17:30:22 +03:00 committed by Sergei Golubchik
parent b8ffd99cee
commit b879b8a5c8
16 changed files with 79 additions and 58 deletions

View file

@ -130,6 +130,13 @@ static inline void my_time_status_init(MYSQL_TIME_STATUS *status)
status->nanoseconds= 0;
}
struct my_timeval
{
longlong tv_sec;
ulong tv_usec;
};
my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date,
ulonglong flags, int *was_cut);
my_bool str_to_DDhhmmssff(const char *str, size_t length, MYSQL_TIME *l_time,
@ -227,7 +234,7 @@ int my_date_to_str(const MYSQL_TIME *l_time, char *to);
int my_datetime_to_str(const MYSQL_TIME *l_time, char *to, uint digits);
int my_TIME_to_str(const MYSQL_TIME *l_time, char *to, uint digits);
int my_timeval_to_str(const struct timeval *tm, char *to, uint dec);
int my_timeval_to_str(const struct my_timeval *tm, char *to, uint dec);
static inline longlong sec_part_shift(longlong second_part, uint digits)
{
@ -258,11 +265,6 @@ static inline void my_time_trunc(MYSQL_TIME *ltime, uint decimals)
#ifdef _WIN32
#define suseconds_t long
#endif
static inline void my_timeval_trunc(struct timeval *tv, uint decimals)
{
tv->tv_usec-= (suseconds_t) my_time_fraction_remainder(tv->tv_usec, decimals);
}
#define hrtime_to_my_time(X) ((my_time_t)hrtime_to_time(X))

View file

@ -1755,7 +1755,7 @@ int my_TIME_to_str(const MYSQL_TIME *l_time, char *to, uint digits)
@param dec Precision, in the range 0..6.
@return The length of the result string.
*/
int my_timeval_to_str(const struct timeval *tm, char *to, uint dec)
int my_timeval_to_str(const struct my_timeval *tm, char *to, uint dec)
{
char *pos= longlong10_to_str((longlong) tm->tv_sec, to, 10);
if (dec)

View file

@ -20,8 +20,7 @@
#include "myisampack.h"
#include "my_time.h"
static const int my_max_usec_value[7]
static const ulong my_max_usec_value[7]
{
0,
900000,
@ -401,7 +400,7 @@ uint my_timestamp_binary_length(uint dec)
@param ptr The pointer to read the value from.
@param dec Precision.
*/
void my_timestamp_from_binary(struct timeval *tm, const uchar *ptr, uint dec)
void my_timestamp_from_binary(struct my_timeval *tm, const uchar *ptr, uint dec)
{
DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
tm->tv_sec= mi_uint4korr(ptr);
@ -413,7 +412,7 @@ void my_timestamp_from_binary(struct timeval *tm, const uchar *ptr, uint dec)
return;
case 1:
case 2:
tm->tv_usec= ((int) ptr[4]) * 10000;
tm->tv_usec= ((uint) ptr[4]) * 10000;
break;
case 3:
case 4:
@ -427,6 +426,18 @@ void my_timestamp_from_binary(struct timeval *tm, const uchar *ptr, uint dec)
set_if_smaller(tm->tv_usec, my_max_usec_value[dec]);
}
/*
This is here mainly for ColumnStore until it is using my_timeval
*/
void my_timestamp_from_binary(struct timeval *tm, const uchar *ptr, uint dec)
{
my_timeval tmp;
my_timestamp_from_binary(&tmp, ptr, dec);
tm->tv_sec= (ulong) tmp.tv_sec;
tm->tv_usec= tmp.tv_usec;
}
/**
Convert MySQL56 in-memory timestamp representation to on-disk representation.
@ -435,7 +446,7 @@ void my_timestamp_from_binary(struct timeval *tm, const uchar *ptr, uint dec)
@param OUT ptr The pointer to store the value to.
@param dec Precision.
*/
void my_timestamp_to_binary(const struct timeval *tm, uchar *ptr, uint dec)
void my_timestamp_to_binary(const struct my_timeval *tm, uchar *ptr, uint dec)
{
DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
/* Stored value must have been previously properly rounded or truncated */

View file

@ -47,7 +47,9 @@ void my_time_packed_to_binary(longlong nr, uchar *ptr, uint dec);
longlong my_time_packed_from_binary(const uchar *ptr, uint dec);
uint my_time_binary_length(uint dec);
void my_timestamp_to_binary(const struct timeval *tm, uchar *ptr, uint dec);
void my_timestamp_to_binary(const struct my_timeval *tm, uchar *ptr, uint dec);
void my_timestamp_from_binary(struct my_timeval *tm, const uchar *ptr, uint dec);
/* For ColumnStore */
void my_timestamp_from_binary(struct timeval *tm, const uchar *ptr, uint dec);
uint my_timestamp_binary_length(uint dec);
/** End of MySQL routines and macros **/

View file

@ -2048,7 +2048,7 @@ int Field::store_text(const char *to, size_t length, CHARSET_INFO *cs,
}
int Field::store_timestamp_dec(const timeval &ts, uint dec)
int Field::store_timestamp_dec(const my_timeval &ts, uint dec)
{
return store_time_dec(Datetime(get_thd(), ts).get_mysql_time(), dec);
}
@ -5403,13 +5403,13 @@ int Field_timestamp::store(longlong nr, bool unsigned_val)
}
int Field_timestamp::store_timestamp_dec(const timeval &tv, uint dec)
int Field_timestamp::store_timestamp_dec(const my_timeval &tv, uint dec)
{
int warn= 0;
time_round_mode_t mode= Datetime::default_round_mode(get_thd());
const Timestamp ts= Timestamp(tv).round(decimals(), mode, &warn);
store_TIMESTAMP(ts);
if (ts.tv().tv_sec == 0 && ts.tv().tv_usec == 0)
if (ts.tv_sec == 0 && ts.tv_usec == 0)
{
/*
The value {tv_sec==0, tv_usec==0} here means '1970-01-01 00:00:00 +00'.
@ -5474,7 +5474,7 @@ int Field_timestamp::store_native(const Native &value)
Field_timestamp*::store_timestamp_dec() do not use the "dec" parameter.
Passing TIME_SECOND_PART_DIGITS is OK.
*/
return store_timestamp_dec(Timestamp(value).tv(), TIME_SECOND_PART_DIGITS);
return store_timestamp_dec(Timestamp(value), TIME_SECOND_PART_DIGITS);
}
@ -5675,7 +5675,7 @@ static longlong read_native(const uchar *from, uint bytes)
#endif
void Field_timestamp_hires::store_TIMEVAL(const timeval &tv)
void Field_timestamp_hires::store_TIMEVAL(const my_timeval &tv)
{
mi_int4store(ptr, tv.tv_sec);
store_bigendian(sec_part_shift(tv.tv_usec, dec), ptr+4, sec_part_bytes(dec));
@ -5693,7 +5693,7 @@ my_time_t Field_timestamp_hires::get_timestamp(const uchar *pos,
bool Field_timestamp_hires::val_native(Native *to)
{
DBUG_ASSERT(marked_for_read());
struct timeval tm;
struct my_timeval tm;
tm.tv_sec= mi_uint4korr(ptr);
tm.tv_usec= (ulong) sec_part_unshift(read_bigendian(ptr+4, sec_part_bytes(dec)), dec);
return Timestamp_or_zero_datetime(Timestamp(tm), tm.tv_sec == 0).
@ -5770,7 +5770,7 @@ void Field_timestamp_with_dec::make_send_field(Send_field *field)
** MySQL-5.6 compatible TIMESTAMP(N)
**************************************************************/
void Field_timestampf::store_TIMEVAL(const timeval &tm)
void Field_timestampf::store_TIMEVAL(const my_timeval &tm)
{
my_timestamp_to_binary(&tm, ptr, dec);
}
@ -5803,10 +5803,10 @@ bool Field_timestampf::is_max()
my_time_t Field_timestampf::get_timestamp(const uchar *pos,
ulong *sec_part) const
{
struct timeval tm;
struct my_timeval tm;
my_timestamp_from_binary(&tm, pos, dec);
*sec_part= tm.tv_usec;
return tm.tv_sec;
return (my_time_t) tm.tv_sec;
}

View file

@ -969,11 +969,13 @@ public:
virtual int store(longlong nr, bool unsigned_val)=0;
virtual int store_decimal(const my_decimal *d)=0;
virtual int store_time_dec(const MYSQL_TIME *ltime, uint dec);
virtual int store_timestamp_dec(const timeval &ts, uint dec);
virtual int store_timestamp_dec(const my_timeval &ts, uint dec);
int store_timestamp(my_time_t timestamp, ulong sec_part)
{
return store_timestamp_dec(Timeval(timestamp, sec_part),
TIME_SECOND_PART_DIGITS);
struct my_timeval tmp;
tmp.tv_sec= (longlong) timestamp;
tmp.tv_usec= (long) sec_part;
return store_timestamp_dec(tmp, TIME_SECOND_PART_DIGITS);
}
/**
Store a value represented in native format
@ -3236,10 +3238,10 @@ class Field_timestamp :public Field_temporal {
protected:
int store_TIME_with_warning(THD *, const Datetime *,
const ErrConv *, int warn);
virtual void store_TIMEVAL(const timeval &tv)= 0;
virtual void store_TIMEVAL(const my_timeval &tv)= 0;
void store_TIMESTAMP(const Timestamp &ts)
{
store_TIMEVAL(ts.tv());
store_TIMEVAL(ts);
}
int zero_time_stored_return_code_with_warning();
public:
@ -3260,7 +3262,7 @@ public:
int store(longlong nr, bool unsigned_val) override;
int store_time_dec(const MYSQL_TIME *ltime, uint dec) override;
int store_decimal(const my_decimal *) override;
int store_timestamp_dec(const timeval &ts, uint dec) override;
int store_timestamp_dec(const my_timeval &ts, uint dec) override;
int save_in_field(Field *to) override;
longlong val_int() override;
String *val_str(String *, String *) override;
@ -3290,7 +3292,7 @@ public:
class Field_timestamp0 :public Field_timestamp
{
void store_TIMEVAL(const timeval &tv) override
void store_TIMEVAL(const my_timeval &tv) override
{
int4store(ptr, tv.tv_sec);
}
@ -3382,7 +3384,7 @@ class Field_timestamp_hires :public Field_timestamp_with_dec {
{
return Type_handler_timestamp::sec_part_bytes(dec);
}
void store_TIMEVAL(const timeval &tv) override;
void store_TIMEVAL(const my_timeval &tv) override;
public:
Field_timestamp_hires(uchar *ptr_arg,
uchar *null_ptr_arg, uchar null_bit_arg,
@ -3411,7 +3413,7 @@ public:
TIMESTAMP(0..6) - MySQL56 version
*/
class Field_timestampf :public Field_timestamp_with_dec {
void store_TIMEVAL(const timeval &tv) override;
void store_TIMEVAL(const my_timeval &tv) override;
public:
Field_timestampf(uchar *ptr_arg,
uchar *null_ptr_arg, uchar null_bit_arg,

View file

@ -1253,8 +1253,8 @@ bool Item_func_unix_timestamp::get_timestamp_value(my_time_t *seconds,
if ((null_value= native.is_null() || native.is_zero_datetime()))
return true;
Timestamp tm(native);
*seconds= tm.tv().tv_sec;
*second_part= tm.tv().tv_usec;
*seconds= (my_time_t) tm.tv_sec;
*second_part= tm.tv_usec;
return false;
}

View file

@ -685,7 +685,7 @@ log_event_print_value(IO_CACHE *file, PRINT_EVENT_INFO *print_event_info,
goto return_null;
char buf[MAX_DATE_STRING_REP_LENGTH];
struct timeval tm;
struct my_timeval tm;
my_timestamp_from_binary(&tm, ptr, meta);
int buflen= my_timeval_to_str(&tm, buf, meta);
my_b_write(file, (uchar*)buf, buflen);

View file

@ -3388,7 +3388,7 @@ public:
WT_THD wt; ///< for deadlock detection
Rows_log_event *m_pending_rows_event;
struct st_trans_time : public timeval
struct st_trans_time : public my_timeval
{
void reset(THD *thd)
{
@ -4299,7 +4299,7 @@ private:
}
public:
timeval transaction_time()
my_timeval transaction_time()
{
if (!in_multi_stmt_transaction_mode())
transaction->start_time.reset(this);

View file

@ -390,7 +390,7 @@ bool Timestamp::to_native(Native *to, uint decimals) const
bool Timestamp::to_TIME(THD *thd, MYSQL_TIME *to, date_mode_t fuzzydate) const
{
return thd->timestamp_to_TIME(to, tv_sec, tv_usec, fuzzydate);
return thd->timestamp_to_TIME(to, (my_time_t) tv_sec, tv_usec, fuzzydate);
}
@ -450,7 +450,7 @@ int Timestamp_or_zero_datetime_native::save_in_field(Field *field,
static Datetime zero(Datetime::zero());
return field->store_time_dec(zero.get_mysql_time(), decimals);
}
return field->store_timestamp_dec(Timestamp(*this).tv(), decimals);
return field->store_timestamp_dec(Timestamp(*this), decimals);
}
@ -782,9 +782,9 @@ void Timestamp::round_or_set_max(uint dec, int *warn)
{
DBUG_ASSERT(dec <= TIME_SECOND_PART_DIGITS);
if (add_nanoseconds_usec(msec_round_add[dec]) &&
(ulonglong) tv_sec++ >= TIMESTAMP_MAX_VALUE)
tv_sec++ >= TIMESTAMP_MAX_VALUE)
{
tv_sec= (time_t) TIMESTAMP_MAX_VALUE;
tv_sec= TIMESTAMP_MAX_VALUE;
tv_usec= TIME_MAX_SECOND_PART;
*warn|= MYSQL_TIME_WARN_OUT_OF_RANGE;
}
@ -1053,9 +1053,9 @@ void Datetime::make_from_datetime(THD *thd, int *warn, const MYSQL_TIME *from,
}
Datetime::Datetime(THD *thd, const timeval &tv)
Datetime::Datetime(THD *thd, const my_timeval &tv)
{
thd->variables.time_zone->gmt_sec_to_TIME(this, tv.tv_sec);
thd->variables.time_zone->gmt_sec_to_TIME(this, (my_time_t) tv.tv_sec);
second_part= tv.tv_usec;
thd->used|= THD::TIME_ZONE_USED;
DBUG_ASSERT(is_valid_value_slow());

View file

@ -2480,7 +2480,7 @@ public:
Datetime(THD *thd, int *warn, const my_decimal *d, date_mode_t fuzzydate)
:Datetime(thd, warn, Sec9(d), fuzzydate)
{ }
Datetime(THD *thd, const timeval &tv);
Datetime(THD *thd, const my_timeval &tv);
Datetime(THD *thd, Item *item, date_mode_t fuzzydate, uint dec)
:Datetime(thd, item, fuzzydate)
@ -2765,7 +2765,7 @@ public:
};
class Timestamp: protected Timeval
class Timestamp: public Timeval
{
static uint binary_length_to_precision(uint length);
protected:
@ -2798,12 +2798,11 @@ public:
Timestamp(my_time_t timestamp, ulong sec_part)
:Timeval(timestamp, sec_part)
{ }
explicit Timestamp(const timeval &tv)
explicit Timestamp(const my_timeval &tv)
:Timeval(tv)
{ }
explicit Timestamp(const Native &native);
Timestamp(THD *thd, const MYSQL_TIME *ltime, uint *error_code);
const struct timeval &tv() const { return *this; }
int cmp(const Timestamp &other) const
{
return tv_sec < other.tv_sec ? -1 :
@ -2934,7 +2933,7 @@ public:
{
return is_zero_datetime() ?
Datetime::zero() :
Datetime(thd, Timestamp(*this).tv());
Datetime(thd, Timestamp(*this));
}
bool is_zero_datetime() const
{

View file

@ -1032,27 +1032,32 @@ public:
};
class Timeval: public timeval
class Timeval: public my_timeval
{
protected:
Timeval() = default;
public:
Timeval(my_time_t sec, ulong usec)
{
tv_sec= (time_t) sec;
tv_sec= (longlong) sec;
/*
Since tv_usec is not always of type ulong, cast usec parameter
explicitly to uint to avoid compiler warnings about losing
integer precision.
*/
DBUG_ASSERT(usec < 1000000);
tv_usec= (uint)usec;
tv_usec= usec;
}
explicit Timeval(const timeval &tv)
:timeval(tv)
{ }
explicit Timeval(const my_timeval &tv)
:my_timeval(tv)
{}
};
static inline void my_timeval_trunc(struct my_timeval *tv, uint decimals)
{
tv->tv_usec-= (suseconds_t) my_time_fraction_remainder(tv->tv_usec, decimals);
}
/*
A value that's either a Timeval or SQL NULL

View file

@ -10396,7 +10396,7 @@ void TR_table::store(uint field_id, ulonglong val)
table->field[field_id]->set_notnull();
}
void TR_table::store(uint field_id, timeval ts)
void TR_table::store(uint field_id, my_timeval ts)
{
table->field[field_id]->store_timestamp(ts.tv_sec, ts.tv_usec);
table->field[field_id]->set_notnull();
@ -10416,7 +10416,7 @@ bool TR_table::update(ulonglong start_id, ulonglong end_id)
store(FLD_BEGIN_TS, thd->transaction_time());
thd->set_time();
timeval end_time= { (time_t) thd->query_start(), int(thd->query_start_sec_part())};
my_timeval end_time= { thd->query_start(), thd->query_start_sec_part()};
store(FLD_TRX_ID, start_id);
store(FLD_COMMIT_ID, end_id);
store(FLD_COMMIT_TS, end_time);

View file

@ -3537,7 +3537,7 @@ public:
@param[in] field number in a TABLE
@param[in] value to store
*/
void store(uint field_id, timeval ts);
void store(uint field_id, my_timeval ts);
/**
Update the transaction_registry right before commit.
@param start_id transaction identifier at start

View file

@ -1075,7 +1075,7 @@ void
Time_zone_system::gmt_sec_to_TIME(MYSQL_TIME *tmp, my_time_t t) const
{
struct tm tmp_tm;
time_t tmp_t= (time_t)t;
time_t tmp_t= (time_t) t;
localtime_r(&tmp_t, &tmp_tm);
localtime_to_TIME(tmp, &tmp_tm);

View file

@ -11781,7 +11781,7 @@ int ha_mroonga::storage_encode_key_timestamp2(Field *field, const uchar *key,
bool truncated = false;
Field_timestampf *timestamp2_field = (Field_timestampf *)field;
struct timeval tm;
struct my_timeval tm;
my_timestamp_from_binary(&tm, key, timestamp2_field->decimals());
MYSQL_TIME mysql_time;
mrn_my_tz_UTC->gmt_sec_to_TIME(&mysql_time, (my_time_t)tm.tv_sec);