Commit c8624163 authored by Monty's avatar Monty Committed by Sergei Golubchik

Updated CONNECT engine to support date and timestamp for the full range.

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

This was done by changing DTVAL to use longlong to internally store
the date/timestamp instead of an int.

I had to preserve the old binary representation used for dates in
TABLE_TYPE=BIN. One consequence is that TABLE_TYPE=BIN cannot support
the full date bit range.
parent b879b8a5
set @@time_zone="+00:00";
create table t1 (c timestamp) ENGINE=Connect TABLE_TYPE=DOS FILE_NAME='func_time_64.dos';
insert into t1 values (from_unixtime(power(2,31)-1));
insert into t1 values (from_unixtime(power(2,32)-1));
select c, unix_timestamp(c) from t1;
c unix_timestamp(c)
2038-01-19 03:14:07 2147483647
2106-02-07 06:28:15 4294967295
drop table t1;
create table t1 (d datetime, c timestamp) ENGINE=Connect TABLE_TYPE=BIN FILE_NAME='func_time_64.dos';
insert into t1 (d,c) values (from_unixtime(power(2,31)-1), from_unixtime(power(2,31)-1));
insert into t1 (d,c) values (from_unixtime(power(2,32)-1), from_unixtime(power(2,32)-1));
insert ignore into t1 values ("1962-03-03","1962-03-03");
Warnings:
Warning 1264 Out of range value for column 'c' at row 1
select d, c, unix_timestamp(c) from t1;
d c unix_timestamp(c)
2038-01-19 03:14:07 2038-01-19 03:14:07 2147483647
1969-12-31 23:59:59 0000-00-00 00:00:00 0
1962-03-03 00:00:00 NULL NULL
Warnings:
Warning 1264 Out of range value for column 'c' at row 2
Warning 1105 Out of range value -1 for column 'c' at row 2
drop table t1;
--source include/have_64bit_timestamp.inc
let $MARIADB_DATADIR= `select @@datadir`;
set @@time_zone="+00:00";
create table t1 (c timestamp) ENGINE=Connect TABLE_TYPE=DOS FILE_NAME='func_time_64.dos';
insert into t1 values (from_unixtime(power(2,31)-1));
insert into t1 values (from_unixtime(power(2,32)-1));
select c, unix_timestamp(c) from t1;
drop table t1;
--remove_file $MARIADB_DATADIR/test/func_time_64.dos
create table t1 (d datetime, c timestamp) ENGINE=Connect TABLE_TYPE=BIN FILE_NAME='func_time_64.dos';
insert into t1 (d,c) values (from_unixtime(power(2,31)-1), from_unixtime(power(2,31)-1));
insert into t1 (d,c) values (from_unixtime(power(2,32)-1), from_unixtime(power(2,32)-1));
insert ignore into t1 values ("1962-03-03","1962-03-03");
select d, c, unix_timestamp(c) from t1;
drop table t1;
--remove_file $MARIADB_DATADIR/test/func_time_64.dos
......@@ -277,6 +277,7 @@ const char *GetFmt(int type, bool un)
case TYPE_BIGINT: fmt = (un) ? "%llu" : "%lld"; break;
case TYPE_DOUBLE: fmt = "%.*lf"; break;
case TYPE_BIN: fmt = "%*x"; break;
case TYPE_DATE: fmt = "%llu"; break;
default: fmt = (un) ? "%u" : "%d"; break;
} // endswitch Type
......@@ -533,6 +534,7 @@ const char *VALUE::GetXfmt(void)
case TYPE_BIGINT: fmt = (Unsigned) ? "%*llu" : "%*lld"; break;
case TYPE_DOUBLE: fmt = "%*.*lf"; break;
case TYPE_BIN: fmt = "%*x"; break;
case TYPE_DATE: fmt = "%*lld"; break;
default: fmt = (Unsigned) ? "%*u" : "%*d"; break;
} // endswitch Type
......@@ -2353,7 +2355,7 @@ bool BINVAL::SetConstFormat(PGLOBAL, FORMAT& fmt)
/* DTVAL public constructor for new void values. */
/***********************************************************************/
DTVAL::DTVAL(PGLOBAL g, int n, int prec, PCSZ fmt)
: TYPVAL<int>((int)0, TYPE_DATE)
: TYPVAL<dtval_timestamp_t>(0, TYPE_DATE)
{
if (!fmt) {
Pdtp = NULL;
......@@ -2369,7 +2371,7 @@ DTVAL::DTVAL(PGLOBAL g, int n, int prec, PCSZ fmt)
/***********************************************************************/
/* DTVAL public constructor from int. */
/***********************************************************************/
DTVAL::DTVAL(int n) : TYPVAL<int>(n, TYPE_DATE)
DTVAL::DTVAL(int n) : TYPVAL<dtval_timestamp_t>(n, TYPE_DATE)
{
Pdtp = NULL;
Len = 19;
......@@ -2462,15 +2464,14 @@ struct tm *DTVAL::GetGmTime(struct tm *tm_buffer)
time_t t = (time_t)Tval;
if (Tval < 0) {
int n;
longlong n;
for (n = 0; t < 0; n += 4)
t += FOURYEARS;
datm = gmtime_mysql(&t, tm_buffer);
if (datm)
datm->tm_year -= n;
datm->tm_year -= (int) n;
} else
datm = gmtime_mysql(&t, tm_buffer);
......@@ -2521,10 +2522,10 @@ bool DTVAL::MakeTime(struct tm *ptm)
} // endif t
Tval= (int) t;
Tval= (dtval_timestamp_t) t;
if (trace(2))
htrc("MakeTime Ival=%d\n", Tval);
htrc("MakeTime Ival=%lld\n", (longlong) Tval);
return false;
} // end of MakeTime
......@@ -2646,7 +2647,7 @@ bool DTVAL::SetValue_pval(PVAL valp, bool chktype)
// Assuming that this timestamp is in milliseconds
SetValue((int)(valp->GetBigintValue() / 1000));
} else
SetValue(valp->GetIntValue());
SetValue(valp->GetBigintValue());
} else
Reset();
......@@ -2688,7 +2689,7 @@ bool DTVAL::SetValue_char(const char *p, int n)
Null = (Nullable && ndv == 0);
} else {
rc = TYPVAL<int>::SetValue_char(p, n);
rc = TYPVAL<dtval_timestamp_t>::SetValue_char(p, n);
Null = (Nullable && Tval == 0);
} // endif Pdtp
......@@ -2711,11 +2712,11 @@ void DTVAL::SetValue_psz(PCSZ p)
MakeDate(NULL, dval, ndv);
if (trace(2))
htrc(" setting date: '%s' -> %d\n", Sdate, Tval);
htrc(" setting date: '%s' -> %lld\n", Sdate, (longlong) Tval);
Null = (Nullable && ndv == 0);
} else {
TYPVAL<int>::SetValue_psz(p);
TYPVAL<dtval_timestamp_t>::SetValue_psz(p);
Null = (Nullable && Tval == 0);
} // endif Pdtp
......@@ -2740,7 +2741,7 @@ void DTVAL::SetValue_pvblk(PVBLK blk, int n)
/***********************************************************************/
/* DTVAL SetValue: get date as an integer. */
/***********************************************************************/
void DTVAL::SetValue(int n)
void DTVAL::SetValue(dtval_timestamp_t n)
{
Tval = n;
......@@ -2774,7 +2775,7 @@ char *DTVAL::GetCharString(char *p)
return Sdate;
} else
sprintf(p, "%d", Tval);
sprintf(p, "%lld", (longlong) Tval);
//Null = false; ??????????????
return p;
......@@ -2806,7 +2807,7 @@ int DTVAL::ShowValue(char *buf, int len)
*buf = '\0'; // DEFAULT VALUE ???
} else
rv = TYPVAL<int>::ShowValue(buf, len);
rv = TYPVAL<dtval_timestamp_t>::ShowValue(buf, len);
return rv;
} // end of ShowValue
......@@ -2888,4 +2889,35 @@ bool DTVAL::FormatValue(PVAL vp, PCSZ fmt)
} // end of FormatValue
void DTVAL::SetBinValue(void* p)
{
#if defined(UNALIGNED_OK)
// x86 can cast non-aligned memory directly
Tval = *(int *)p;
#else
int tmp;
memcpy(&tmp, p, sizeof(tmp));
Tval= tmp;
#endif
Null = false;
} // end of SetBinValue
bool DTVAL::GetBinValue(void *buf, int buflen, bool go)
{
if (go)
#if defined(UNALIGNED_OK)
// x86 can cast non-aligned memory directly
*(int *)buf = (int) Tval;
#else
{
int tmp= (int) Tval;
memcpy(buf, &tmp, sizeof(tmp));
}
#endif
Null = false;
return false;
} // end of GetBinValue
/* -------------------------- End of Value --------------------------- */
......@@ -60,6 +60,9 @@ DllExport ulonglong CharToNumber(PCSZ, int, ulonglong, bool,
bool *minus = NULL, bool *rc = NULL);
DllExport BYTE OpBmp(PGLOBAL g, OPVAL opc);
/* Type for date and timestamps */
typedef longlong dtval_timestamp_t;
/***********************************************************************/
/* Class VALUE represents a constant or variable of any valid type. */
/***********************************************************************/
......@@ -407,21 +410,24 @@ class DllExport BINVAL: public VALUE {
/***********************************************************************/
/* Class DTVAL: represents a time stamp value. */
/***********************************************************************/
class DllExport DTVAL : public TYPVAL<int> {
class DllExport DTVAL : public TYPVAL<dtval_timestamp_t> {
public:
// Constructors
DTVAL(PGLOBAL g, int n, int p, PCSZ fmt);
DTVAL(int n);
using TYPVAL<int>::SetValue;
using TYPVAL<dtval_timestamp_t>::SetValue;
// Implementation
virtual bool SetValue_pval(PVAL valp, bool chktype);
virtual bool SetValue_char(const char *p, int n);
virtual void SetValue_psz(PCSZ s);
virtual void SetValue_pvblk(PVBLK blk, int n);
virtual void SetValue(int n);
virtual void SetValue(dtval_timestamp_t n);
virtual void SetBinValue(void* p);
virtual bool GetBinValue(void *buf, int buflen, bool go);
virtual PSZ GetCharValue(void) { return Sdate; }
virtual char *GetCharString(char *p);
virtual char *GetCharString(char *p);
virtual int ShowValue(char *buf, int len);
virtual bool FormatValue(PVAL vp, PCSZ fmt);
bool SetFormat(PGLOBAL g, PCSZ fmt, int len, int year = 0);
......@@ -438,7 +444,7 @@ class DllExport DTVAL : public TYPVAL<int> {
protected:
// Default constructor not to be used
DTVAL(void) : TYPVAL<int>() {}
DTVAL(void) : TYPVAL<dtval_timestamp_t>() {}
// Members
static int Shift; // Time zone shift in seconds
......
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