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) ...@@ -277,6 +277,7 @@ const char *GetFmt(int type, bool un)
case TYPE_BIGINT: fmt = (un) ? "%llu" : "%lld"; break; case TYPE_BIGINT: fmt = (un) ? "%llu" : "%lld"; break;
case TYPE_DOUBLE: fmt = "%.*lf"; break; case TYPE_DOUBLE: fmt = "%.*lf"; break;
case TYPE_BIN: fmt = "%*x"; break; case TYPE_BIN: fmt = "%*x"; break;
case TYPE_DATE: fmt = "%llu"; break;
default: fmt = (un) ? "%u" : "%d"; break; default: fmt = (un) ? "%u" : "%d"; break;
} // endswitch Type } // endswitch Type
...@@ -533,6 +534,7 @@ const char *VALUE::GetXfmt(void) ...@@ -533,6 +534,7 @@ const char *VALUE::GetXfmt(void)
case TYPE_BIGINT: fmt = (Unsigned) ? "%*llu" : "%*lld"; break; case TYPE_BIGINT: fmt = (Unsigned) ? "%*llu" : "%*lld"; break;
case TYPE_DOUBLE: fmt = "%*.*lf"; break; case TYPE_DOUBLE: fmt = "%*.*lf"; break;
case TYPE_BIN: fmt = "%*x"; break; case TYPE_BIN: fmt = "%*x"; break;
case TYPE_DATE: fmt = "%*lld"; break;
default: fmt = (Unsigned) ? "%*u" : "%*d"; break; default: fmt = (Unsigned) ? "%*u" : "%*d"; break;
} // endswitch Type } // endswitch Type
...@@ -2353,7 +2355,7 @@ bool BINVAL::SetConstFormat(PGLOBAL, FORMAT& fmt) ...@@ -2353,7 +2355,7 @@ bool BINVAL::SetConstFormat(PGLOBAL, FORMAT& fmt)
/* DTVAL public constructor for new void values. */ /* DTVAL public constructor for new void values. */
/***********************************************************************/ /***********************************************************************/
DTVAL::DTVAL(PGLOBAL g, int n, int prec, PCSZ fmt) 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) { if (!fmt) {
Pdtp = NULL; Pdtp = NULL;
...@@ -2369,7 +2371,7 @@ DTVAL::DTVAL(PGLOBAL g, int n, int prec, PCSZ fmt) ...@@ -2369,7 +2371,7 @@ DTVAL::DTVAL(PGLOBAL g, int n, int prec, PCSZ fmt)
/***********************************************************************/ /***********************************************************************/
/* DTVAL public constructor from int. */ /* 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; Pdtp = NULL;
Len = 19; Len = 19;
...@@ -2462,15 +2464,14 @@ struct tm *DTVAL::GetGmTime(struct tm *tm_buffer) ...@@ -2462,15 +2464,14 @@ struct tm *DTVAL::GetGmTime(struct tm *tm_buffer)
time_t t = (time_t)Tval; time_t t = (time_t)Tval;
if (Tval < 0) { if (Tval < 0) {
int n; longlong n;
for (n = 0; t < 0; n += 4) for (n = 0; t < 0; n += 4)
t += FOURYEARS; t += FOURYEARS;
datm = gmtime_mysql(&t, tm_buffer); datm = gmtime_mysql(&t, tm_buffer);
if (datm) if (datm)
datm->tm_year -= n; datm->tm_year -= (int) n;
} else } else
datm = gmtime_mysql(&t, tm_buffer); datm = gmtime_mysql(&t, tm_buffer);
...@@ -2521,10 +2522,10 @@ bool DTVAL::MakeTime(struct tm *ptm) ...@@ -2521,10 +2522,10 @@ bool DTVAL::MakeTime(struct tm *ptm)
} // endif t } // endif t
Tval= (int) t; Tval= (dtval_timestamp_t) t;
if (trace(2)) if (trace(2))
htrc("MakeTime Ival=%d\n", Tval); htrc("MakeTime Ival=%lld\n", (longlong) Tval);
return false; return false;
} // end of MakeTime } // end of MakeTime
...@@ -2646,7 +2647,7 @@ bool DTVAL::SetValue_pval(PVAL valp, bool chktype) ...@@ -2646,7 +2647,7 @@ bool DTVAL::SetValue_pval(PVAL valp, bool chktype)
// Assuming that this timestamp is in milliseconds // Assuming that this timestamp is in milliseconds
SetValue((int)(valp->GetBigintValue() / 1000)); SetValue((int)(valp->GetBigintValue() / 1000));
} else } else
SetValue(valp->GetIntValue()); SetValue(valp->GetBigintValue());
} else } else
Reset(); Reset();
...@@ -2688,7 +2689,7 @@ bool DTVAL::SetValue_char(const char *p, int n) ...@@ -2688,7 +2689,7 @@ bool DTVAL::SetValue_char(const char *p, int n)
Null = (Nullable && ndv == 0); Null = (Nullable && ndv == 0);
} else { } else {
rc = TYPVAL<int>::SetValue_char(p, n); rc = TYPVAL<dtval_timestamp_t>::SetValue_char(p, n);
Null = (Nullable && Tval == 0); Null = (Nullable && Tval == 0);
} // endif Pdtp } // endif Pdtp
...@@ -2711,11 +2712,11 @@ void DTVAL::SetValue_psz(PCSZ p) ...@@ -2711,11 +2712,11 @@ void DTVAL::SetValue_psz(PCSZ p)
MakeDate(NULL, dval, ndv); MakeDate(NULL, dval, ndv);
if (trace(2)) if (trace(2))
htrc(" setting date: '%s' -> %d\n", Sdate, Tval); htrc(" setting date: '%s' -> %lld\n", Sdate, (longlong) Tval);
Null = (Nullable && ndv == 0); Null = (Nullable && ndv == 0);
} else { } else {
TYPVAL<int>::SetValue_psz(p); TYPVAL<dtval_timestamp_t>::SetValue_psz(p);
Null = (Nullable && Tval == 0); Null = (Nullable && Tval == 0);
} // endif Pdtp } // endif Pdtp
...@@ -2740,7 +2741,7 @@ void DTVAL::SetValue_pvblk(PVBLK blk, int n) ...@@ -2740,7 +2741,7 @@ void DTVAL::SetValue_pvblk(PVBLK blk, int n)
/***********************************************************************/ /***********************************************************************/
/* DTVAL SetValue: get date as an integer. */ /* DTVAL SetValue: get date as an integer. */
/***********************************************************************/ /***********************************************************************/
void DTVAL::SetValue(int n) void DTVAL::SetValue(dtval_timestamp_t n)
{ {
Tval = n; Tval = n;
...@@ -2774,7 +2775,7 @@ char *DTVAL::GetCharString(char *p) ...@@ -2774,7 +2775,7 @@ char *DTVAL::GetCharString(char *p)
return Sdate; return Sdate;
} else } else
sprintf(p, "%d", Tval); sprintf(p, "%lld", (longlong) Tval);
//Null = false; ?????????????? //Null = false; ??????????????
return p; return p;
...@@ -2806,7 +2807,7 @@ int DTVAL::ShowValue(char *buf, int len) ...@@ -2806,7 +2807,7 @@ int DTVAL::ShowValue(char *buf, int len)
*buf = '\0'; // DEFAULT VALUE ??? *buf = '\0'; // DEFAULT VALUE ???
} else } else
rv = TYPVAL<int>::ShowValue(buf, len); rv = TYPVAL<dtval_timestamp_t>::ShowValue(buf, len);
return rv; return rv;
} // end of ShowValue } // end of ShowValue
...@@ -2888,4 +2889,35 @@ bool DTVAL::FormatValue(PVAL vp, PCSZ fmt) ...@@ -2888,4 +2889,35 @@ bool DTVAL::FormatValue(PVAL vp, PCSZ fmt)
} // end of FormatValue } // 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 --------------------------- */ /* -------------------------- End of Value --------------------------- */
...@@ -60,6 +60,9 @@ DllExport ulonglong CharToNumber(PCSZ, int, ulonglong, bool, ...@@ -60,6 +60,9 @@ DllExport ulonglong CharToNumber(PCSZ, int, ulonglong, bool,
bool *minus = NULL, bool *rc = NULL); bool *minus = NULL, bool *rc = NULL);
DllExport BYTE OpBmp(PGLOBAL g, OPVAL opc); 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. */ /* Class VALUE represents a constant or variable of any valid type. */
/***********************************************************************/ /***********************************************************************/
...@@ -407,19 +410,22 @@ class DllExport BINVAL: public VALUE { ...@@ -407,19 +410,22 @@ class DllExport BINVAL: public VALUE {
/***********************************************************************/ /***********************************************************************/
/* Class DTVAL: represents a time stamp value. */ /* Class DTVAL: represents a time stamp value. */
/***********************************************************************/ /***********************************************************************/
class DllExport DTVAL : public TYPVAL<int> {
class DllExport DTVAL : public TYPVAL<dtval_timestamp_t> {
public: public:
// Constructors // Constructors
DTVAL(PGLOBAL g, int n, int p, PCSZ fmt); DTVAL(PGLOBAL g, int n, int p, PCSZ fmt);
DTVAL(int n); DTVAL(int n);
using TYPVAL<int>::SetValue; using TYPVAL<dtval_timestamp_t>::SetValue;
// Implementation // Implementation
virtual bool SetValue_pval(PVAL valp, bool chktype); virtual bool SetValue_pval(PVAL valp, bool chktype);
virtual bool SetValue_char(const char *p, int n); virtual bool SetValue_char(const char *p, int n);
virtual void SetValue_psz(PCSZ s); virtual void SetValue_psz(PCSZ s);
virtual void SetValue_pvblk(PVBLK blk, int n); 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 PSZ GetCharValue(void) { return Sdate; }
virtual char *GetCharString(char *p); virtual char *GetCharString(char *p);
virtual int ShowValue(char *buf, int len); virtual int ShowValue(char *buf, int len);
...@@ -438,7 +444,7 @@ class DllExport DTVAL : public TYPVAL<int> { ...@@ -438,7 +444,7 @@ class DllExport DTVAL : public TYPVAL<int> {
protected: protected:
// Default constructor not to be used // Default constructor not to be used
DTVAL(void) : TYPVAL<int>() {} DTVAL(void) : TYPVAL<dtval_timestamp_t>() {}
// Members // Members
static int Shift; // Time zone shift in seconds 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