Add support for indexing of timestamp, timestamptz and date in MOT

This commit is contained in:
Vinoth Veeraraghavan
2020-10-29 20:18:28 +08:00
parent f0d27718b1
commit b5d52a3488
14 changed files with 5595 additions and 47 deletions

View File

@ -60,6 +60,7 @@ typedef union {
X(DATE, "Date") \ X(DATE, "Date") \
X(TIME, "Time") \ X(TIME, "Time") \
X(TIMESTAMP, "Timestamp") \ X(TIMESTAMP, "Timestamp") \
X(TIMESTAMPTZ, "TimestampTZ") \
X(INTERVAL, "Interval") \ X(INTERVAL, "Interval") \
X(TINTERVAL, "TInterval") \ X(TINTERVAL, "TInterval") \
X(TIMETZ, "TimeTZ") \ X(TIMETZ, "TimeTZ") \

View File

@ -30,6 +30,10 @@
#include "utilities.h" #include "utilities.h"
#include "mot_error.h" #include "mot_error.h"
extern uint16_t MOTTimestampToStr(uintptr_t src, char* destBuf, size_t len);
extern uint16_t MOTTimestampTzToStr(uintptr_t src, char* destBuf, size_t len);
extern uint16_t MOTDateToStr(uintptr_t src, char* destBuf, size_t len);
namespace MOT { namespace MOT {
DECLARE_LOGGER(Column, Storage) DECLARE_LOGGER(Column, Storage)
@ -293,11 +297,11 @@ bool ColumnLONG::PackKey(uint8_t* dest, uintptr_t src, size_t len, uint8_t fill)
{ {
uint64_t tmp = (uint64_t)GetBytes8(src); uint64_t tmp = (uint64_t)GetBytes8(src);
*(uint64_t*)(dest + 1) = be64toh(tmp); *(uint64_t*)(dest + 1) = be64toh(tmp);
if (tmp & 0x8000000000000000) if (tmp & 0x8000000000000000) {
*dest = 0x00; *dest = 0x00;
else } else {
*dest = 0x01; *dest = 0x01;
}
return true; return true;
} }
@ -340,10 +344,11 @@ bool ColumnFLOAT::PackKey(uint8_t* dest, uintptr_t src, size_t len, uint8_t fill
t.m_r = (uint32_t)GetBytes4(src); t.m_r = (uint32_t)GetBytes4(src);
// keep sign // keep sign
if (t.m_r & FLOAT_SIGN_MASK) if (t.m_r & FLOAT_SIGN_MASK) {
*dest = 0x00; *dest = 0x00;
else } else {
*dest = 0x01; *dest = 0x01;
}
// remove sign and move exp to a most significant byte // remove sign and move exp to a most significant byte
t.m_r <<= 1; t.m_r <<= 1;
// extract exp // extract exp
@ -477,15 +482,13 @@ void ColumnDATE::Unpack(uint8_t* data, uintptr_t* dest, size_t& len)
void ColumnDATE::SetKeySize() void ColumnDATE::SetKeySize()
{ {
m_keySize = m_size; m_keySize = m_size + 1;
} }
uint16_t ColumnDATE::PrintValue(uint8_t* data, char* destBuf, size_t len) uint16_t ColumnDATE::PrintValue(uint8_t* data, char* destBuf, size_t len)
{ {
if (len >= 3) { if (len >= MOT_MAXDATELEN) {
errno_t erc = snprintf_s(destBuf, len, len - 1, "NaN"); return MOTDateToStr(GetBytes4(*(uint32_t*)(data + m_offset)), destBuf, len);
securec_check_ss(erc, "\0", "\0");
return erc;
} }
return 0; return 0;
} }
@ -635,8 +638,13 @@ bool ColumnTIMESTAMP::Pack(uint8_t* dest, uintptr_t src, size_t len)
bool ColumnTIMESTAMP::PackKey(uint8_t* dest, uintptr_t src, size_t len, uint8_t fill) bool ColumnTIMESTAMP::PackKey(uint8_t* dest, uintptr_t src, size_t len, uint8_t fill)
{ {
*(uint64_t*)(dest) = be64toh((uint64_t)GetBytes8(src)); uint64_t tmp = (uint64_t)GetBytes8(src);
*(uint64_t*)(dest + 1) = be64toh(tmp);
if (tmp & 0x8000000000000000) {
*dest = 0x00;
} else {
*dest = 0x01;
}
return true; return true;
} }
@ -647,15 +655,50 @@ void ColumnTIMESTAMP::Unpack(uint8_t* data, uintptr_t* dest, size_t& len)
void ColumnTIMESTAMP::SetKeySize() void ColumnTIMESTAMP::SetKeySize()
{ {
m_keySize = m_size; m_keySize = m_size + 1;
} }
uint16_t ColumnTIMESTAMP::PrintValue(uint8_t* data, char* destBuf, size_t len) uint16_t ColumnTIMESTAMP::PrintValue(uint8_t* data, char* destBuf, size_t len)
{ {
if (len >= 3) { if (len >= MOT_MAXDATELEN) {
errno_t erc = snprintf_s(destBuf, len, len - 1, "NaN"); return MOTTimestampToStr(GetBytes8(*(uint64_t*)(data + m_offset)), destBuf, len);
securec_check_ss(erc, "\0", "\0"); }
return erc; return 0;
}
bool ColumnTIMESTAMPTZ::Pack(uint8_t* dest, uintptr_t src, size_t len)
{
*(uint64_t*)(dest + m_offset) = (uint64_t)GetBytes8(src);
return true;
}
bool ColumnTIMESTAMPTZ::PackKey(uint8_t* dest, uintptr_t src, size_t len, uint8_t fill)
{
uint64_t tmp = (uint64_t)GetBytes8(src);
*(uint64_t*)(dest + 1) = be64toh(tmp);
if (tmp & 0x8000000000000000) {
*dest = 0x00;
} else {
*dest = 0x01;
}
return true;
}
void ColumnTIMESTAMPTZ::Unpack(uint8_t* data, uintptr_t* dest, size_t& len)
{
*dest = GetBytes8(*(uint64_t*)(data + m_offset));
}
void ColumnTIMESTAMPTZ::SetKeySize()
{
m_keySize = m_size + 1;
}
uint16_t ColumnTIMESTAMPTZ::PrintValue(uint8_t* data, char* destBuf, size_t len)
{
if (len >= MOT_MAXDATELEN) {
return MOTTimestampTzToStr(GetBytes8(*(uint64_t*)(data + m_offset)), destBuf, len);
} }
return 0; return 0;
} }

View File

@ -29,6 +29,8 @@
#include "utils/elog.h" #include "utils/elog.h"
#include "securec.h" #include "securec.h"
#define MOT_MAXDATELEN 128
namespace MOT { namespace MOT {
/** /**
* @brief The Column class describes a single field in a row in a table. * @brief The Column class describes a single field in a row in a table.

View File

@ -49,7 +49,7 @@
#include "optimizer/restrictinfo.h" #include "optimizer/restrictinfo.h"
#include "utils/memutils.h" #include "utils/memutils.h"
#include "utils/rel.h" #include "utils/rel.h"
#include "utils/date.h"
#include "utils/syscache.h" #include "utils/syscache.h"
#include "utils/partitionkey.h" #include "utils/partitionkey.h"
#include "catalog/heap.h" #include "catalog/heap.h"
@ -2275,6 +2275,13 @@ inline bool GetKeyOperation(OpExpr* op, KEY_OPER& oper)
case BPCHAREQOID: case BPCHAREQOID:
case TEXTEQOID: case TEXTEQOID:
case 92: // CHAREQ case 92: // CHAREQ
case 2536: // timestampVStimestamptz
case 2542: // timestamptzVStimestamp
case 2347: // dateVStimestamp
case 2360: // dateVStimestamptz
case 2373: // timestampVSdate
case 2386: // timestamptzVSdate
case TIMESTAMPEQOID:
oper = KEY_OPER::READ_KEY_EXACT; oper = KEY_OPER::READ_KEY_EXACT;
break; break;
case FLOAT8LTOID: case FLOAT8LTOID:
@ -2294,6 +2301,13 @@ inline bool GetKeyOperation(OpExpr* op, KEY_OPER& oper)
case 1058: // BPCHARLT case 1058: // BPCHARLT
case 631: // CHARLT case 631: // CHARLT
case TEXTLTOID: case TEXTLTOID:
case 2534: // timestampVStimestamptz
case 2540: // timestamptzVStimestamp
case 2345: // dateVStimestamp
case 2358: // dateVStimestamptz
case 2371: // timestampVSdate
case 2384: // timestamptzVSdate
case TIMESTAMPLTOID:
oper = KEY_OPER::READ_KEY_BEFORE; oper = KEY_OPER::READ_KEY_BEFORE;
break; break;
case FLOAT8LEOID: case FLOAT8LEOID:
@ -2313,6 +2327,13 @@ inline bool GetKeyOperation(OpExpr* op, KEY_OPER& oper)
case 1059: // BPCHARLE case 1059: // BPCHARLE
case 632: // CHARLE case 632: // CHARLE
case 665: // TEXTLE case 665: // TEXTLE
case 2535: // timestampVStimestamptz
case 2541: // timestamptzVStimestamp
case 2346: // dateVStimestamp
case 2359: // dateVStimestamptz
case 2372: // timestampVSdate
case 2385: // timestamptzVSdate
case TIMESTAMPLEOID:
oper = KEY_OPER::READ_KEY_OR_PREV; oper = KEY_OPER::READ_KEY_OR_PREV;
break; break;
case FLOAT8GTOID: case FLOAT8GTOID:
@ -2332,6 +2353,13 @@ inline bool GetKeyOperation(OpExpr* op, KEY_OPER& oper)
case 1060: // BPCHARGT case 1060: // BPCHARGT
case 633: // CHARGT case 633: // CHARGT
case TEXTGTOID: // TEXTGT case TEXTGTOID: // TEXTGT
case 2538: // timestampVStimestamptz
case 2544: // timestamptzVStimestamp
case 2349: // dateVStimestamp
case 2362: // dateVStimestamptz
case 2375: // timestampVSdate
case 2388: // timestamptzVSdate
case TIMESTAMPGTOID:
oper = KEY_OPER::READ_KEY_AFTER; oper = KEY_OPER::READ_KEY_AFTER;
break; break;
case FLOAT8GEOID: case FLOAT8GEOID:
@ -2351,6 +2379,13 @@ inline bool GetKeyOperation(OpExpr* op, KEY_OPER& oper)
case 1061: // BPCHARGE case 1061: // BPCHARGE
case 634: // CHARGE case 634: // CHARGE
case 667: // TEXTGE case 667: // TEXTGE
case 2537: // timestampVStimestamptz
case 2543: // timestamptzVStimestamp
case 2348: // dateVStimestamp
case 2361: // dateVStimestamptz
case 2374: // timestampVSdate
case 2387: // timestamptzVSdate
case TIMESTAMPGEOID:
oper = KEY_OPER::READ_KEY_OR_NEXT; oper = KEY_OPER::READ_KEY_OR_NEXT;
break; break;
case OID_TEXT_LIKE_OP: case OID_TEXT_LIKE_OP:
@ -2486,8 +2521,10 @@ bool IsMOTExpr(RelOptInfo* baserel, MOTFdwStateSt* state, MatchIndexArr* marr, E
case T_FuncExpr: { case T_FuncExpr: {
FuncExpr* func = (FuncExpr*)expr; FuncExpr* func = (FuncExpr*)expr;
if (func->funcformat == COERCE_IMPLICIT_CAST) { if (func->funcformat == COERCE_IMPLICIT_CAST || func->funcformat == COERCE_EXPLICIT_CAST) {
isOperatorMOTReady = IsMOTExpr(baserel, state, marr, (Expr*)linitial(func->args), result, setLocal); isOperatorMOTReady = IsMOTExpr(baserel, state, marr, (Expr*)linitial(func->args), result, setLocal);
} else if (list_length(func->args) == 0) {
isOperatorMOTReady = true;
} }
break; break;
@ -2504,3 +2541,36 @@ bool IsMOTExpr(RelOptInfo* baserel, MOTFdwStateSt* state, MatchIndexArr* marr, E
return isOperatorMOTReady; return isOperatorMOTReady;
} }
uint16_t MOTTimestampToStr(uintptr_t src, char* destBuf, size_t len)
{
char* tmp = nullptr;
Timestamp timestamp = DatumGetTimestamp(src);
tmp = DatumGetCString(DirectFunctionCall1(timestamp_out, timestamp));
errno_t erc = snprintf_s(destBuf, len, len - 1, tmp);
pfree_ext(tmp);
securec_check_ss(erc, "\0", "\0");
return erc;
}
uint16_t MOTTimestampTzToStr(uintptr_t src, char* destBuf, size_t len)
{
char* tmp = nullptr;
TimestampTz timestamp = DatumGetTimestampTz(src);
tmp = DatumGetCString(DirectFunctionCall1(timestamptz_out, timestamp));
errno_t erc = snprintf_s(destBuf, len, len - 1, tmp);
pfree_ext(tmp);
securec_check_ss(erc, "\0", "\0");
return erc;
}
uint16_t MOTDateToStr(uintptr_t src, char* destBuf, size_t len)
{
char* tmp = nullptr;
DateADT date = DatumGetDateADT(src);
tmp = DatumGetCString(DirectFunctionCall1(date_out, date));
errno_t erc = snprintf_s(destBuf, len, len - 1, tmp);
pfree_ext(tmp);
securec_check_ss(erc, "\0", "\0");
return erc;
}

View File

@ -1492,9 +1492,11 @@ static MOT::RC TableFieldType(const ColumnDef* colDef, MOT::MOT_CATALOG_FIELD_TY
type = MOT::MOT_CATALOG_FIELD_TYPES::MOT_TYPE_TIME; type = MOT::MOT_CATALOG_FIELD_TYPES::MOT_TYPE_TIME;
break; break;
case TIMESTAMPOID: case TIMESTAMPOID:
case TIMESTAMPTZOID:
type = MOT::MOT_CATALOG_FIELD_TYPES::MOT_TYPE_TIMESTAMP; type = MOT::MOT_CATALOG_FIELD_TYPES::MOT_TYPE_TIMESTAMP;
break; break;
case TIMESTAMPTZOID:
type = MOT::MOT_CATALOG_FIELD_TYPES::MOT_TYPE_TIMESTAMPTZ;
break;
case INTERVALOID: case INTERVALOID:
type = MOT::MOT_CATALOG_FIELD_TYPES::MOT_TYPE_INTERVAL; type = MOT::MOT_CATALOG_FIELD_TYPES::MOT_TYPE_INTERVAL;
break; break;
@ -2227,7 +2229,7 @@ void MOTAdaptor::CreateKeyBuffer(Relation rel, MOTFdwStateSt* festate, int start
} }
DatumToMOTKey(col, DatumToMOTKey(col,
expr->expr, expr,
val, val,
desc->attrs[orgCols[i] - 1]->atttypid, desc->attrs[orgCols[i] - 1]->atttypid,
buf + offset, buf + offset,
@ -2451,7 +2453,7 @@ void MOTAdaptor::DatumToMOT(MOT::Column* col, Datum datum, Oid type, uint8_t* da
} }
void MOTAdaptor::DatumToMOTKey( void MOTAdaptor::DatumToMOTKey(
MOT::Column* col, Expr* expr, Datum datum, Oid type, uint8_t* data, size_t len, KEY_OPER oper, uint8_t fill) MOT::Column* col, ExprState* expr, Datum datum, Oid type, uint8_t* data, size_t len, KEY_OPER oper, uint8_t fill)
{ {
EnsureSafeThreadAccessInline(); EnsureSafeThreadAccessInline();
switch (type) { switch (type) {
@ -2460,8 +2462,8 @@ void MOTAdaptor::DatumToMOTKey(
case VARCHAROID: case VARCHAROID:
case CLOBOID: case CLOBOID:
case BPCHAROID: { case BPCHAROID: {
if (expr && IsA(expr, Const)) { // OA: LLVM passes nullptr for expr parameter if (expr && expr->expr && IsA(expr->expr, Const)) { // OA: LLVM passes nullptr for expr parameter
Const* c = (Const*)expr; Const* c = (Const*)expr->expr;
if (c->constbyval) { if (c->constbyval) {
errno_t erc = memset_s(data, len, 0x00, len); errno_t erc = memset_s(data, len, 0x00, len);
@ -2500,8 +2502,8 @@ void MOTAdaptor::DatumToMOTKey(
break; break;
} }
case FLOAT4OID: { case FLOAT4OID: {
if (expr && IsA(expr, Const)) { // OA: LLVM passes nullptr for expr parameter if (expr && expr->expr && IsA(expr->expr, Const)) { // OA: LLVM passes nullptr for expr parameter
Const* c = (Const*)expr; Const* c = (Const*)expr->expr;
if (c->consttype == FLOAT8OID) { if (c->consttype == FLOAT8OID) {
MOT::DoubleConvT dc; MOT::DoubleConvT dc;
@ -2525,6 +2527,42 @@ void MOTAdaptor::DatumToMOTKey(
break; break;
} }
case TIMESTAMPOID: {
if (expr->resultType == TIMESTAMPTZOID) {
Timestamp result = DatumGetTimestamp(DirectFunctionCall1(timestamptz_timestamp, datum));
col->PackKey(data, result, col->m_size);
} else if (expr->resultType == DATEOID) {
Timestamp result = DatumGetTimestamp(DirectFunctionCall1(date_timestamp, datum));
col->PackKey(data, result, col->m_size);
} else {
col->PackKey(data, datum, col->m_size);
}
break;
}
case TIMESTAMPTZOID: {
if (expr->resultType == TIMESTAMPOID) {
TimestampTz result = DatumGetTimestampTz(DirectFunctionCall1(timestamp_timestamptz, datum));
col->PackKey(data, result, col->m_size);
} else if (expr->resultType == DATEOID) {
TimestampTz result = DatumGetTimestampTz(DirectFunctionCall1(date_timestamptz, datum));
col->PackKey(data, result, col->m_size);
} else {
col->PackKey(data, datum, col->m_size);
}
break;
}
case DATEOID: {
if (expr->resultType == TIMESTAMPOID) {
DateADT result = DatumGetDateADT(DirectFunctionCall1(timestamp_date, datum));
col->PackKey(data, result, col->m_size);
} else if (expr->resultType == TIMESTAMPTZOID) {
DateADT result = DatumGetDateADT(DirectFunctionCall1(timestamptz_date, datum));
col->PackKey(data, result, col->m_size);
} else {
col->PackKey(data, datum, col->m_size);
}
break;
}
default: default:
col->PackKey(data, datum, col->m_size); col->PackKey(data, datum, col->m_size);
break; break;

View File

@ -382,7 +382,7 @@ public:
// data conversion // data conversion
static void DatumToMOT(MOT::Column* col, Datum datum, Oid type, uint8_t* data); static void DatumToMOT(MOT::Column* col, Datum datum, Oid type, uint8_t* data);
static void DatumToMOTKey(MOT::Column* col, Expr* expr, Datum datum, Oid type, uint8_t* data, size_t len, static void DatumToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, Oid type, uint8_t* data, size_t len,
KEY_OPER oper, uint8_t fill = 0x00); KEY_OPER oper, uint8_t fill = 0x00);
static void MOTToDatum(MOT::Table* table, const Form_pg_attribute attr, uint8_t* data, Datum* value, bool* is_null); static void MOTToDatum(MOT::Table* table, const Form_pg_attribute attr, uint8_t* data, Datum* value, bool* is_null);

View File

@ -291,6 +291,10 @@ static Oid column_type_to_pg(MOT::MOT_CATALOG_FIELD_TYPES column_type)
pg_type = TIMESTAMPOID; pg_type = TIMESTAMPOID;
break; break;
case MOT::MOT_TYPE_TIMESTAMPTZ:
pg_type = TIMESTAMPTZOID;
break;
case MOT::MOT_TYPE_INTERVAL: case MOT::MOT_TYPE_INTERVAL:
pg_type = INTERVALOID; pg_type = INTERVALOID;
break; break;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@ test: mot/single_tpcc_queries
test: mot/single_basic_sql test: mot/single_basic_sql
test: mot/single_merge_compatible mot/single_merge_explain mot/single_merge_explain_pretty mot/single_merge_privilege test: mot/single_merge_compatible mot/single_merge_explain mot/single_merge_explain_pretty mot/single_merge_privilege
test: mot/single_hw_alter_session test: mot/single_hw_alter_session
test: mot/single_boolean mot/single_char mot/single_varchar mot/single_text mot/single_int2 mot/single_int4 mot/single_int8 mot/single_float4 mot/single_float8 mot/single_numeric test: mot/single_boolean mot/single_char mot/single_varchar mot/single_text mot/single_int2 mot/single_int4 mot/single_int8 mot/single_float4 mot/single_float8 mot/single_numeric mot/single_node_timestamp mot/single_node_timestamptz mot/single_node_date
test: mot/single_numerology test: mot/single_numerology
test: mot/single_namespace test: mot/single_namespace
test: mot/single_analyze_dropdb test: mot/single_analyze_dropdb

View File

@ -0,0 +1,278 @@
--
-- DATE
--
CREATE FOREIGN TABLE DATE_TBL (f1 date primary key);
INSERT INTO DATE_TBL VALUES ('1957-04-09');
INSERT INTO DATE_TBL VALUES ('1957-06-13');
INSERT INTO DATE_TBL VALUES ('1996-02-28');
INSERT INTO DATE_TBL VALUES ('1996-02-29');
INSERT INTO DATE_TBL VALUES ('1996-03-01');
INSERT INTO DATE_TBL VALUES ('1996-03-02');
INSERT INTO DATE_TBL VALUES ('1997-02-28');
INSERT INTO DATE_TBL VALUES ('1997-02-29');
INSERT INTO DATE_TBL VALUES ('1997-03-01');
INSERT INTO DATE_TBL VALUES ('1997-03-02');
INSERT INTO DATE_TBL VALUES ('2000-04-01');
INSERT INTO DATE_TBL VALUES ('2000-04-02');
INSERT INTO DATE_TBL VALUES ('2000-04-03');
INSERT INTO DATE_TBL VALUES ('2038-04-08');
INSERT INTO DATE_TBL VALUES ('2039-04-09');
INSERT INTO DATE_TBL VALUES ('2040-04-10');
SELECT f1 AS "Fifteen" FROM DATE_TBL;
SELECT f1 AS "Nine" FROM DATE_TBL WHERE f1 < '2000-01-01';
SELECT f1 AS "Three" FROM DATE_TBL
WHERE f1 BETWEEN '2000-01-01' AND '2001-01-01';
--
-- Check all the documented input formats
--
SET datestyle TO iso; -- display results in ISO
SET datestyle TO ymd;
SELECT date 'January 8, 1999';
SELECT date '1999-01-08';
SELECT date '1999-01-18';
SELECT date '1/8/1999';
SELECT date '1/18/1999';
SELECT date '18/1/1999';
SELECT date '01/02/03';
SELECT date '19990108';
SELECT date '990108';
SELECT date '1999.008';
SELECT date 'J2451187';
SELECT date 'January 8, 99 BC';
SELECT date '99-Jan-08';
SELECT date '1999-Jan-08';
SELECT date '08-Jan-99';
SELECT date '08-Jan-1999';
SELECT date 'Jan-08-99';
SELECT date 'Jan-08-1999';
SELECT date '99-08-Jan';
SELECT date '1999-08-Jan';
SELECT date '99 Jan 08';
SELECT date '1999 Jan 08';
SELECT date '08 Jan 99';
SELECT date '08 Jan 1999';
SELECT date 'Jan 08 99';
SELECT date 'Jan 08 1999';
SELECT date '99 08 Jan';
SELECT date '1999 08 Jan';
SELECT date '99-01-08';
SELECT date '1999-01-08';
SELECT date '08-01-99';
SELECT date '08-01-1999';
SELECT date '01-08-99';
SELECT date '01-08-1999';
SELECT date '99-08-01';
SELECT date '1999-08-01';
SELECT date '99 01 08';
SELECT date '1999 01 08';
SELECT date '08 01 99';
SELECT date '08 01 1999';
SELECT date '01 08 99';
SELECT date '01 08 1999';
SELECT date '99 08 01';
SELECT date '1999 08 01';
SET datestyle TO dmy;
SELECT date 'January 8, 1999';
SELECT date '1999-01-08';
SELECT date '1999-01-18';
SELECT date '1/8/1999';
SELECT date '1/18/1999';
SELECT date '18/1/1999';
SELECT date '01/02/03';
SELECT date '19990108';
SELECT date '990108';
SELECT date '1999.008';
SELECT date 'J2451187';
SELECT date 'January 8, 99 BC';
SELECT date '99-Jan-08';
SELECT date '1999-Jan-08';
SELECT date '08-Jan-99';
SELECT date '08-Jan-1999';
SELECT date 'Jan-08-99';
SELECT date 'Jan-08-1999';
SELECT date '99-08-Jan';
SELECT date '1999-08-Jan';
SELECT date '99 Jan 08';
SELECT date '1999 Jan 08';
SELECT date '08 Jan 99';
SELECT date '08 Jan 1999';
SELECT date 'Jan 08 99';
SELECT date 'Jan 08 1999';
SELECT date '99 08 Jan';
SELECT date '1999 08 Jan';
SELECT date '99-01-08';
SELECT date '1999-01-08';
SELECT date '08-01-99';
SELECT date '08-01-1999';
SELECT date '01-08-99';
SELECT date '01-08-1999';
SELECT date '99-08-01';
SELECT date '1999-08-01';
SELECT date '99 01 08';
SELECT date '1999 01 08';
SELECT date '08 01 99';
SELECT date '08 01 1999';
SELECT date '01 08 99';
SELECT date '01 08 1999';
SELECT date '99 08 01';
SELECT date '1999 08 01';
SET datestyle TO mdy;
SELECT date 'January 8, 1999';
SELECT date '1999-01-08';
SELECT date '1999-01-18';
SELECT date '1/8/1999';
SELECT date '1/18/1999';
SELECT date '18/1/1999';
SELECT date '01/02/03';
SELECT date '19990108';
SELECT date '990108';
SELECT date '1999.008';
SELECT date 'J2451187';
SELECT date 'January 8, 99 BC';
SELECT date '99-Jan-08';
SELECT date '1999-Jan-08';
SELECT date '08-Jan-99';
SELECT date '08-Jan-1999';
SELECT date 'Jan-08-99';
SELECT date 'Jan-08-1999';
SELECT date '99-08-Jan';
SELECT date '1999-08-Jan';
SELECT date '99 Jan 08';
SELECT date '1999 Jan 08';
SELECT date '08 Jan 99';
SELECT date '08 Jan 1999';
SELECT date 'Jan 08 99';
SELECT date 'Jan 08 1999';
SELECT date '99 08 Jan';
SELECT date '1999 08 Jan';
SELECT date '99-01-08';
SELECT date '1999-01-08';
SELECT date '08-01-99';
SELECT date '08-01-1999';
SELECT date '01-08-99';
SELECT date '01-08-1999';
SELECT date '99-08-01';
SELECT date '1999-08-01';
SELECT date '99 01 08';
SELECT date '1999 01 08';
SELECT date '08 01 99';
SELECT date '08 01 1999';
SELECT date '01 08 99';
SELECT date '01 08 1999';
SELECT date '99 08 01';
SELECT date '1999 08 01';
RESET datestyle;
--
-- Simple math
-- Leave most of it for the horology tests
--
SELECT f1 - date '2000-01-01' AS "Days From 2K" FROM DATE_TBL;
SELECT f1 - date 'epoch' AS "Days From Epoch" FROM DATE_TBL;
SELECT date 'yesterday' - date 'today' AS "One day";
SELECT date 'today' - date 'tomorrow' AS "One day";
SELECT date 'yesterday' - date 'tomorrow' AS "Two days";
SELECT date 'tomorrow' - date 'today' AS "One day";
SELECT date 'today' - date 'yesterday' AS "One day";
SELECT date 'tomorrow' - date 'yesterday' AS "Two days";
--
-- test extract!
--
-- century
--
SELECT EXTRACT(CENTURY FROM DATE '0101-12-31 BC'); -- -2
SELECT EXTRACT(CENTURY FROM DATE '0100-12-31 BC'); -- -1
SELECT EXTRACT(CENTURY FROM DATE '0001-12-31 BC'); -- -1
SELECT EXTRACT(CENTURY FROM DATE '0001-01-01'); -- 1
SELECT EXTRACT(CENTURY FROM DATE '0001-01-01 AD'); -- 1
SELECT EXTRACT(CENTURY FROM DATE '1900-12-31'); -- 19
SELECT EXTRACT(CENTURY FROM DATE '1901-01-01'); -- 20
SELECT EXTRACT(CENTURY FROM DATE '2000-12-31'); -- 20
SELECT EXTRACT(CENTURY FROM DATE '2001-01-01'); -- 21
SELECT EXTRACT(CENTURY FROM CURRENT_DATE)>=21 AS True; -- true
--
-- millennium
--
SELECT EXTRACT(MILLENNIUM FROM DATE '0001-12-31 BC'); -- -1
SELECT EXTRACT(MILLENNIUM FROM DATE '0001-01-01 AD'); -- 1
SELECT EXTRACT(MILLENNIUM FROM DATE '1000-12-31'); -- 1
SELECT EXTRACT(MILLENNIUM FROM DATE '1001-01-01'); -- 2
SELECT EXTRACT(MILLENNIUM FROM DATE '2000-12-31'); -- 2
SELECT EXTRACT(MILLENNIUM FROM DATE '2001-01-01'); -- 3
-- next test to be fixed on the turn of the next millennium;-)
SELECT EXTRACT(MILLENNIUM FROM CURRENT_DATE); -- 3
--
-- decade
--
SELECT EXTRACT(DECADE FROM DATE '1994-12-25'); -- 199
SELECT EXTRACT(DECADE FROM DATE '0010-01-01'); -- 1
SELECT EXTRACT(DECADE FROM DATE '0009-12-31'); -- 0
SELECT EXTRACT(DECADE FROM DATE '0001-01-01 BC'); -- 0
SELECT EXTRACT(DECADE FROM DATE '0002-12-31 BC'); -- -1
SELECT EXTRACT(DECADE FROM DATE '0011-01-01 BC'); -- -1
SELECT EXTRACT(DECADE FROM DATE '0012-12-31 BC'); -- -2
--
-- some other types:
--
-- on a timestamp.
SELECT EXTRACT(CENTURY FROM NOW())>=21 AS True; -- true
SELECT EXTRACT(CENTURY FROM TIMESTAMP '1970-03-20 04:30:00.00000'); -- 20
-- on an interval
SELECT EXTRACT(CENTURY FROM INTERVAL '100 y'); -- 1
SELECT EXTRACT(CENTURY FROM INTERVAL '99 y'); -- 0
SELECT EXTRACT(CENTURY FROM INTERVAL '-99 y'); -- 0
SELECT EXTRACT(CENTURY FROM INTERVAL '-100 y'); -- -1
--
-- test trunc function!
--
SELECT DATE_TRUNC('MILLENNIUM', TIMESTAMP '1970-03-20 04:30:00.00000'); -- 1001
SELECT DATE_TRUNC('MILLENNIUM', DATE '1970-03-20'); -- 1001-01-01
SELECT DATE_TRUNC('CENTURY', TIMESTAMP '1970-03-20 04:30:00.00000'); -- 1901
SELECT DATE_TRUNC('CENTURY', DATE '1970-03-20'); -- 1901
SELECT DATE_TRUNC('CENTURY', DATE '2004-08-10'); -- 2001-01-01
SELECT DATE_TRUNC('CENTURY', DATE '0002-02-04'); -- 0001-01-01
SELECT DATE_TRUNC('CENTURY', DATE '0055-08-10 BC'); -- 0100-01-01 BC
SELECT DATE_TRUNC('DECADE', DATE '1993-12-25'); -- 1990-01-01
SELECT DATE_TRUNC('DECADE', DATE '0004-12-25'); -- 0001-01-01 BC
SELECT DATE_TRUNC('DECADE', DATE '0002-12-31 BC'); -- 0011-01-01 BC
--
-- test infinity
--
select 'infinity'::date, '-infinity'::date;
select 'infinity'::date > 'today'::date as t;
select '-infinity'::date < 'today'::date as t;
select isfinite('infinity'::date), isfinite('-infinity'::date), isfinite('today'::date);

View File

@ -0,0 +1,219 @@
--
-- TIMESTAMP
--
CREATE FOREIGN TABLE TIMESTAMP_TBL (d1 timestamp without time zone primary key);
-- Test shorthand input values
-- We can't just "select" the results since they aren't constants; test for
-- equality instead. We can do that by running the test inside a transaction
-- block, within which the value of 'now' shouldn't change. We also check
-- that 'now' *does* change over a reasonable interval such as 100 msec.
-- NOTE: it is possible for this part of the test to fail if the transaction
-- block is entered exactly at local midnight; then 'now' and 'today' have
-- the same values and the counts will come out different.
INSERT INTO TIMESTAMP_TBL VALUES ('now');
SELECT pg_sleep(0.1);
INSERT INTO TIMESTAMP_TBL VALUES ('now');
INSERT INTO TIMESTAMP_TBL VALUES ('today');
INSERT INTO TIMESTAMP_TBL VALUES ('yesterday');
INSERT INTO TIMESTAMP_TBL VALUES ('tomorrow');
-- time zone should be ignored by this data type
INSERT INTO TIMESTAMP_TBL VALUES ('Mon Feb 10 00:00:00 1997');
INSERT INTO TIMESTAMP_TBL VALUES ('Mon Feb 10 00:00:00 1997 EST');
INSERT INTO TIMESTAMP_TBL VALUES ('Mon Feb 10 00:00:00 1997 zulu');
SELECT count(*) AS One FROM TIMESTAMP_TBL WHERE d1 = timestamp without time zone 'today';
SELECT count(*) AS Three FROM TIMESTAMP_TBL WHERE d1 = timestamp without time zone 'tomorrow';
SELECT count(*) AS One FROM TIMESTAMP_TBL WHERE d1 = timestamp without time zone 'yesterday';
SELECT count(*) AS One FROM TIMESTAMP_TBL WHERE d1 = timestamp without time zone 'now';
DELETE FROM TIMESTAMP_TBL;
-- verify uniform transaction time within transaction block
INSERT INTO TIMESTAMP_TBL VALUES ('now');
SELECT pg_sleep(0.1);
INSERT INTO TIMESTAMP_TBL VALUES ('now');
SELECT pg_sleep(0.1);
SELECT count(*) AS two FROM TIMESTAMP_TBL WHERE d1 = timestamp without time zone 'now';
DELETE FROM TIMESTAMP_TBL;
-- Special values
INSERT INTO TIMESTAMP_TBL VALUES ('-infinity');
INSERT INTO TIMESTAMP_TBL VALUES ('infinity');
INSERT INTO TIMESTAMP_TBL VALUES ('epoch');
-- Obsolete special values
INSERT INTO TIMESTAMP_TBL VALUES ('invalid');
INSERT INTO TIMESTAMP_TBL VALUES ('undefined');
INSERT INTO TIMESTAMP_TBL VALUES ('current');
-- Postgres v6.0 standard output format
INSERT INTO TIMESTAMP_TBL VALUES ('Mon Feb 10 17:32:01 1997 PST');
-- Variations on Postgres v6.1 standard output format
INSERT INTO TIMESTAMP_TBL VALUES ('Mon Feb 10 17:32:01.000001 1997 PST');
INSERT INTO TIMESTAMP_TBL VALUES ('Mon Feb 10 17:32:01.999999 1997 PST');
INSERT INTO TIMESTAMP_TBL VALUES ('Mon Feb 10 17:32:01.4 1997 PST');
INSERT INTO TIMESTAMP_TBL VALUES ('Mon Feb 10 17:32:01.5 1997 PST');
INSERT INTO TIMESTAMP_TBL VALUES ('Mon Feb 10 17:32:01.6 1997 PST');
-- ISO 8601 format
INSERT INTO TIMESTAMP_TBL VALUES ('1997-01-02');
INSERT INTO TIMESTAMP_TBL VALUES ('1997-01-02 03:04:05');
INSERT INTO TIMESTAMP_TBL VALUES ('1997-02-10 17:32:01-08');
INSERT INTO TIMESTAMP_TBL VALUES ('1997-02-10 17:32:01-0800');
INSERT INTO TIMESTAMP_TBL VALUES ('1997-02-10 17:32:01 -08:00');
INSERT INTO TIMESTAMP_TBL VALUES ('19970210 173201 -0800');
INSERT INTO TIMESTAMP_TBL VALUES ('1997-06-10 17:32:01 -07:00');
INSERT INTO TIMESTAMP_TBL VALUES ('2001-09-22T18:19:20');
-- POSIX format (note that the timezone abbrev is just decoration here)
INSERT INTO TIMESTAMP_TBL VALUES ('2000-03-15 08:14:01 GMT+8');
INSERT INTO TIMESTAMP_TBL VALUES ('2000-03-15 13:14:02 GMT-1');
INSERT INTO TIMESTAMP_TBL VALUES ('2000-03-15 12:14:03 GMT-2');
INSERT INTO TIMESTAMP_TBL VALUES ('2000-03-15 03:14:04 PST+8');
INSERT INTO TIMESTAMP_TBL VALUES ('2000-03-15 02:14:05 MST+7:00');
-- Variations for acceptable input formats
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 10 17:32:01 1997 -0800');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 10 17:32:01 1997');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 10 5:32PM 1997');
INSERT INTO TIMESTAMP_TBL VALUES ('1997/02/10 17:32:01-0800');
INSERT INTO TIMESTAMP_TBL VALUES ('1997-02-10 17:32:01 PST');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb-10-1997 17:32:01 PST');
INSERT INTO TIMESTAMP_TBL VALUES ('02-10-1997 17:32:01 PST');
INSERT INTO TIMESTAMP_TBL VALUES ('19970210 173201 PST');
set datestyle to ymd;
INSERT INTO TIMESTAMP_TBL VALUES ('97FEB10 5:32:01PM UTC');
INSERT INTO TIMESTAMP_TBL VALUES ('97/02/10 17:32:01 UTC');
reset datestyle;
INSERT INTO TIMESTAMP_TBL VALUES ('1997.041 17:32:01 UTC');
INSERT INTO TIMESTAMP_TBL VALUES ('19970210 173201 America/New_York');
-- this fails (even though TZ is a no-op, we still look it up)
INSERT INTO TIMESTAMP_TBL VALUES ('19970710 173201 America/Does_not_exist');
-- Check date conversion and date arithmetic
INSERT INTO TIMESTAMP_TBL VALUES ('1997-06-10 18:32:01 PDT');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 10 17:32:01 1997');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 11 17:32:01 1997');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 12 17:32:01 1997');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 13 17:32:01 1997');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 14 17:32:01 1997');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 15 17:32:01 1997');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 1997');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 0097 BC');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 0097');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 0597');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 1097');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 1697');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 1797');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 1897');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 1997');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 2097');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 28 17:32:01 1996');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 29 17:32:01 1996');
INSERT INTO TIMESTAMP_TBL VALUES ('Mar 01 17:32:01 1996');
INSERT INTO TIMESTAMP_TBL VALUES ('Dec 30 17:32:01 1996');
INSERT INTO TIMESTAMP_TBL VALUES ('Dec 31 17:32:01 1996');
INSERT INTO TIMESTAMP_TBL VALUES ('Jan 01 17:32:01 1997');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 28 17:32:01 1997');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 29 17:32:01 1997');
INSERT INTO TIMESTAMP_TBL VALUES ('Mar 01 17:32:01 1997');
INSERT INTO TIMESTAMP_TBL VALUES ('Dec 30 17:32:01 1997');
INSERT INTO TIMESTAMP_TBL VALUES ('Dec 31 17:32:01 1997');
INSERT INTO TIMESTAMP_TBL VALUES ('Dec 31 17:32:01 1999');
INSERT INTO TIMESTAMP_TBL VALUES ('Jan 01 17:32:01 2000');
INSERT INTO TIMESTAMP_TBL VALUES ('Dec 31 17:32:01 2000');
INSERT INTO TIMESTAMP_TBL VALUES ('Jan 01 17:32:01 2001');
-- Currently unsupported syntax and ranges
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 -0097');
INSERT INTO TIMESTAMP_TBL VALUES ('Feb 16 17:32:01 5097 BC');
SELECT '' AS "64", d1 FROM TIMESTAMP_TBL;
-- Demonstrate functions and operators
SELECT '' AS "48", d1 FROM TIMESTAMP_TBL
WHERE d1 > timestamp without time zone '1997-01-02';
SELECT '' AS "15", d1 FROM TIMESTAMP_TBL
WHERE d1 < timestamp without time zone '1997-01-02';
SELECT '' AS one, d1 FROM TIMESTAMP_TBL
WHERE d1 = timestamp without time zone '1997-01-02';
SELECT '' AS "63", d1 FROM TIMESTAMP_TBL
WHERE d1 != timestamp without time zone '1997-01-02';
SELECT '' AS "16", d1 FROM TIMESTAMP_TBL
WHERE d1 <= timestamp without time zone '1997-01-02';
SELECT '' AS "49", d1 FROM TIMESTAMP_TBL
WHERE d1 >= timestamp without time zone '1997-01-02';
SELECT '' AS "54", d1 - timestamp without time zone '1997-01-02' AS diff
FROM TIMESTAMP_TBL WHERE d1 BETWEEN '1902-01-01' AND '2038-01-01';
SELECT '' AS date_trunc_week, date_trunc( 'week', timestamp '2004-02-29 15:44:17.71393' ) AS week_trunc;
-- Test casting within a BETWEEN qualifier
SELECT '' AS "54", d1 - timestamp without time zone '1997-01-02' AS diff
FROM TIMESTAMP_TBL
WHERE d1 BETWEEN timestamp without time zone '1902-01-01'
AND timestamp without time zone '2038-01-01';
SELECT '' AS "54", d1 as "timestamp",
date_part( 'year', d1) AS year, date_part( 'month', d1) AS month,
date_part( 'day', d1) AS day, date_part( 'hour', d1) AS hour,
date_part( 'minute', d1) AS minute, date_part( 'second', d1) AS second
FROM TIMESTAMP_TBL WHERE d1 BETWEEN '1902-01-01' AND '2038-01-01';
SELECT '' AS "54", d1 as "timestamp",
date_part( 'quarter', d1) AS quarter, date_part( 'msec', d1) AS msec,
date_part( 'usec', d1) AS usec
FROM TIMESTAMP_TBL WHERE d1 BETWEEN '1902-01-01' AND '2038-01-01';
SELECT '' AS "54", d1 as "timestamp",
date_part( 'isoyear', d1) AS isoyear, date_part( 'week', d1) AS week,
date_part( 'dow', d1) AS dow
FROM TIMESTAMP_TBL WHERE d1 BETWEEN '1902-01-01' AND '2038-01-01';
-- TO_CHAR()
SELECT '' AS to_char_1, to_char(d1, 'DAY Day day DY Dy dy MONTH Month month RM MON Mon mon')
FROM TIMESTAMP_TBL;
SELECT '' AS to_char_2, to_char(d1, 'FMDAY FMDay FMday FMMONTH FMMonth FMmonth FMRM')
FROM TIMESTAMP_TBL;
SELECT '' AS to_char_3, to_char(d1, 'Y,YYY YYYY YYY YY Y CC Q MM WW DDD DD D J')
FROM TIMESTAMP_TBL;
SELECT '' AS to_char_4, to_char(d1, 'FMY,YYY FMYYYY FMYYY FMYY FMY FMCC FMQ FMMM FMWW FMDDD FMDD FMD FMJ')
FROM TIMESTAMP_TBL;
SELECT '' AS to_char_5, to_char(d1, 'HH HH12 HH24 MI SS SSSS')
FROM TIMESTAMP_TBL;
SELECT '' AS to_char_6, to_char(d1, E'"HH:MI:SS is" HH:MI:SS "\\"text between quote marks\\""')
FROM TIMESTAMP_TBL;
SELECT '' AS to_char_7, to_char(d1, 'HH24--text--MI--text--SS')
FROM TIMESTAMP_TBL;
SELECT '' AS to_char_8, to_char(d1, 'YYYYTH YYYYth Jth')
FROM TIMESTAMP_TBL;
SELECT '' AS to_char_9, to_char(d1, 'YYYY A.D. YYYY a.d. YYYY bc HH:MI:SS P.M. HH:MI:SS p.m. HH:MI:SS pm')
FROM TIMESTAMP_TBL;
SELECT '' AS to_char_10, to_char(d1, 'IYYY IYY IY I IW IDDD ID')
FROM TIMESTAMP_TBL;
SELECT '' AS to_char_11, to_char(d1, 'FMIYYY FMIYY FMIY FMI FMIW FMIDDD FMID')
FROM TIMESTAMP_TBL;

View File

@ -0,0 +1,370 @@
--
-- TIMESTAMPTZ
--
CREATE FOREIGN TABLE TIMESTAMPTZ_TBL (d1 timestamp with time zone primary key);
-- Test shorthand input values
-- We can't just "select" the results since they aren't constants; test for
-- equality instead. We can do that by running the test inside a transaction
-- block, within which the value of 'now' shouldn't change. We also check
-- that 'now' *does* change over a reasonable interval such as 100 msec.
-- NOTE: it is possible for this part of the test to fail if the transaction
-- block is entered exactly at local midnight; then 'now' and 'today' have
-- the same values and the counts will come out different.
INSERT INTO TIMESTAMPTZ_TBL VALUES ('now');
SELECT pg_sleep(0.1);
INSERT INTO TIMESTAMPTZ_TBL VALUES ('now');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('today');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('yesterday');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('tomorrow');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('tomorrow EST');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('tomorrow zulu');
SELECT count(*) AS One FROM TIMESTAMPTZ_TBL WHERE d1 = timestamp with time zone 'today';
SELECT count(*) AS One FROM TIMESTAMPTZ_TBL WHERE d1 = timestamp with time zone 'tomorrow';
SELECT count(*) AS One FROM TIMESTAMPTZ_TBL WHERE d1 = timestamp with time zone 'yesterday';
SELECT count(*) AS One FROM TIMESTAMPTZ_TBL WHERE d1 = timestamp with time zone 'now';
DELETE FROM TIMESTAMPTZ_TBL;
-- verify uniform transaction time within transaction block
INSERT INTO TIMESTAMPTZ_TBL VALUES ('now');
SELECT pg_sleep(0.1);
INSERT INTO TIMESTAMPTZ_TBL VALUES ('now');
SELECT pg_sleep(0.1);
SELECT count(*) AS two FROM TIMESTAMPTZ_TBL WHERE d1 = timestamp with time zone 'now';
DELETE FROM TIMESTAMPTZ_TBL;
-- Special values
INSERT INTO TIMESTAMPTZ_TBL VALUES ('-infinity');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('infinity');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('epoch');
-- Obsolete special values
INSERT INTO TIMESTAMPTZ_TBL VALUES ('invalid');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('undefined');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('current');
-- Postgres v6.0 standard output format
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mon Feb 10 17:32:01 1997 PST');
-- Variations on Postgres v6.1 standard output format
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mon Feb 10 17:32:01.000001 1997 PST');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mon Feb 10 17:32:01.999999 1997 PST');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mon Feb 10 17:32:01.4 1997 PST');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mon Feb 10 17:32:01.5 1997 PST');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mon Feb 10 17:32:01.6 1997 PST');
-- ISO 8601 format
INSERT INTO TIMESTAMPTZ_TBL VALUES ('1997-01-02');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('1997-01-02 03:04:05');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('1997-02-10 17:32:01-08');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('1997-02-10 17:32:01-0800');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('1997-02-10 17:32:01 -08:00');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('19970210 173201 -0800');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('1997-06-10 17:32:01 -07:00');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('2001-09-22T18:19:20');
-- POSIX format (note that the timezone abbrev is just decoration here)
INSERT INTO TIMESTAMPTZ_TBL VALUES ('2000-03-15 08:14:01 GMT+8');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('2000-03-15 13:14:02 GMT-1');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('2000-03-15 12:14:03 GMT-2');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('2000-03-15 03:14:04 PST+8');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('2000-03-15 02:14:05 MST+7:00');
-- Variations for acceptable input formats
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 10 17:32:01 1997 -0800');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 10 17:32:01 1997');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 10 5:32PM 1997');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('1997/02/10 17:32:01-0800');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('1997-02-10 17:32:01 PST');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb-10-1997 17:32:01 PST');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('02-10-1997 17:32:01 PST');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('19970210 173201 PST');
set datestyle to ymd;
INSERT INTO TIMESTAMPTZ_TBL VALUES ('97FEB10 5:32:01PM UTC');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('97/02/10 17:32:01 UTC');
reset datestyle;
INSERT INTO TIMESTAMPTZ_TBL VALUES ('1997.041 17:32:01 UTC');
-- timestamps at different timezones
INSERT INTO TIMESTAMPTZ_TBL VALUES ('19970210 173201 America/New_York');
SELECT '19970210 173201' AT TIME ZONE 'America/New_York';
INSERT INTO TIMESTAMPTZ_TBL VALUES ('19970710 173201 America/New_York');
SELECT '19970710 173201' AT TIME ZONE 'America/New_York';
INSERT INTO TIMESTAMPTZ_TBL VALUES ('19970710 173201 America/Does_not_exist');
SELECT '19970710 173201' AT TIME ZONE 'America/Does_not_exist';
-- Daylight saving time for timestamps beyond 32-bit time_t range.
SELECT '20500710 173201 Europe/Helsinki'::timestamptz; -- DST
SELECT '20500110 173201 Europe/Helsinki'::timestamptz; -- non-DST
SELECT '205000-07-10 17:32:01 Europe/Helsinki'::timestamptz; -- DST
SELECT '205000-01-10 17:32:01 Europe/Helsinki'::timestamptz; -- non-DST
-- Check date conversion and date arithmetic
INSERT INTO TIMESTAMPTZ_TBL VALUES ('1997-06-10 18:32:01 PDT');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 10 17:32:01 1997');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 11 17:32:01 1997');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 12 17:32:01 1997');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 13 17:32:01 1997');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 14 17:32:01 1997');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 15 17:32:01 1997');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 1997');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 0097 BC');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 0097');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 0597');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 1097');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 1697');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 1797');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 1897');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 1997');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 2097');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 28 17:32:01 1996');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 29 17:32:01 1996');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mar 01 17:32:01 1996');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Dec 30 17:32:01 1996');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Dec 31 17:32:01 1996');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Jan 01 17:32:01 1997');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 28 17:32:01 1997');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 29 17:32:01 1997');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Mar 01 17:32:01 1997');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Dec 30 17:32:01 1997');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Dec 31 17:32:01 1997');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Dec 31 17:32:01 1999');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Jan 01 17:32:01 2000');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Dec 31 17:32:01 2000');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Jan 01 17:32:01 2001');
-- Currently unsupported syntax and ranges
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 -0097');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('Feb 16 17:32:01 5097 BC');
-- Alternative field order that we've historically supported (sort of)
-- with regular and POSIXy timezone specs
SELECT 'Wed Jul 11 10:51:14 America/New_York 2001'::timestamptz;
SELECT 'Wed Jul 11 10:51:14 GMT-4 2001'::timestamptz;
SELECT 'Wed Jul 11 10:51:14 GMT+4 2001'::timestamptz;
SELECT 'Wed Jul 11 10:51:14 PST-03:00 2001'::timestamptz;
SELECT 'Wed Jul 11 10:51:14 PST+03:00 2001'::timestamptz;
SELECT '' AS "64", d1 FROM TIMESTAMPTZ_TBL;
-- Demonstrate functions and operators
SELECT '' AS "48", d1 FROM TIMESTAMPTZ_TBL
WHERE d1 > timestamp with time zone '1997-01-02';
SELECT '' AS "15", d1 FROM TIMESTAMPTZ_TBL
WHERE d1 < timestamp with time zone '1997-01-02';
SELECT '' AS one, d1 FROM TIMESTAMPTZ_TBL
WHERE d1 = timestamp with time zone '1997-01-02';
SELECT '' AS "63", d1 FROM TIMESTAMPTZ_TBL
WHERE d1 != timestamp with time zone '1997-01-02';
SELECT '' AS "16", d1 FROM TIMESTAMPTZ_TBL
WHERE d1 <= timestamp with time zone '1997-01-02';
SELECT '' AS "49", d1 FROM TIMESTAMPTZ_TBL
WHERE d1 >= timestamp with time zone '1997-01-02';
SELECT '' AS "54", d1 - timestamp with time zone '1997-01-02' AS diff
FROM TIMESTAMPTZ_TBL WHERE d1 BETWEEN '1902-01-01' AND '2038-01-01';
SELECT '' AS date_trunc_week, date_trunc( 'week', timestamp with time zone '2004-02-29 15:44:17.71393' ) AS week_trunc;
-- Test casting within a BETWEEN qualifier
SELECT '' AS "54", d1 - timestamp with time zone '1997-01-02' AS diff
FROM TIMESTAMPTZ_TBL
WHERE d1 BETWEEN timestamp with time zone '1902-01-01' AND timestamp with time zone '2038-01-01';
SELECT '' AS "54", d1 as timestamptz,
date_part( 'year', d1) AS year, date_part( 'month', d1) AS month,
date_part( 'day', d1) AS day, date_part( 'hour', d1) AS hour,
date_part( 'minute', d1) AS minute, date_part( 'second', d1) AS second
FROM TIMESTAMPTZ_TBL WHERE d1 BETWEEN '1902-01-01' AND '2038-01-01';
SELECT '' AS "54", d1 as timestamptz,
date_part( 'quarter', d1) AS quarter, date_part( 'msec', d1) AS msec,
date_part( 'usec', d1) AS usec
FROM TIMESTAMPTZ_TBL WHERE d1 BETWEEN '1902-01-01' AND '2038-01-01';
SELECT '' AS "54", d1 as timestamptz,
date_part( 'isoyear', d1) AS isoyear, date_part( 'week', d1) AS week,
date_part( 'dow', d1) AS dow
FROM TIMESTAMPTZ_TBL WHERE d1 BETWEEN '1902-01-01' AND '2038-01-01';
-- TO_CHAR()
SELECT '' AS to_char_1, to_char(d1, 'DAY Day day DY Dy dy MONTH Month month RM MON Mon mon')
FROM TIMESTAMPTZ_TBL;
SELECT '' AS to_char_2, to_char(d1, 'FMDAY FMDay FMday FMMONTH FMMonth FMmonth FMRM')
FROM TIMESTAMPTZ_TBL;
SELECT '' AS to_char_3, to_char(d1, 'Y,YYY YYYY YYY YY Y CC Q MM WW DDD DD D J')
FROM TIMESTAMPTZ_TBL;
SELECT '' AS to_char_4, to_char(d1, 'FMY,YYY FMYYYY FMYYY FMYY FMY FMCC FMQ FMMM FMWW FMDDD FMDD FMD FMJ')
FROM TIMESTAMPTZ_TBL;
SELECT '' AS to_char_5, to_char(d1, 'HH HH12 HH24 MI SS SSSS')
FROM TIMESTAMPTZ_TBL;
SELECT '' AS to_char_6, to_char(d1, E'"HH:MI:SS is" HH:MI:SS "\\"text between quote marks\\""')
FROM TIMESTAMPTZ_TBL;
SELECT '' AS to_char_7, to_char(d1, 'HH24--text--MI--text--SS')
FROM TIMESTAMPTZ_TBL;
SELECT '' AS to_char_8, to_char(d1, 'YYYYTH YYYYth Jth')
FROM TIMESTAMPTZ_TBL;
SELECT '' AS to_char_9, to_char(d1, 'YYYY A.D. YYYY a.d. YYYY bc HH:MI:SS P.M. HH:MI:SS p.m. HH:MI:SS pm')
FROM TIMESTAMPTZ_TBL;
SELECT '' AS to_char_10, to_char(d1, 'IYYY IYY IY I IW IDDD ID')
FROM TIMESTAMPTZ_TBL;
SELECT '' AS to_char_11, to_char(d1, 'FMIYYY FMIYY FMIY FMI FMIW FMIDDD FMID')
FROM TIMESTAMPTZ_TBL;
--
-- Test behavior with a dynamic (time-varying) timezone abbreviation.
-- These tests rely on the knowledge that MSK (Europe/Moscow standard time)
-- moved forwards in Mar 2011 and backwards again in Oct 2014.
--
SET TimeZone to 'UTC';
SELECT '2011-03-27 00:00:00 Europe/Moscow'::timestamptz;
SELECT '2011-03-27 01:00:00 Europe/Moscow'::timestamptz;
SELECT '2011-03-27 01:59:59 Europe/Moscow'::timestamptz;
SELECT '2011-03-27 02:00:00 Europe/Moscow'::timestamptz;
SELECT '2011-03-27 02:00:01 Europe/Moscow'::timestamptz;
SELECT '2011-03-27 02:59:59 Europe/Moscow'::timestamptz;
SELECT '2011-03-27 03:00:00 Europe/Moscow'::timestamptz;
SELECT '2011-03-27 03:00:01 Europe/Moscow'::timestamptz;
SELECT '2011-03-27 04:00:00 Europe/Moscow'::timestamptz;
SELECT '2011-03-27 00:00:00 MSK'::timestamptz;
SELECT '2011-03-27 01:00:00 MSK'::timestamptz;
SELECT '2011-03-27 01:59:59 MSK'::timestamptz;
SELECT '2011-03-27 02:00:00 MSK'::timestamptz;
SELECT '2011-03-27 02:00:01 MSK'::timestamptz;
SELECT '2011-03-27 02:59:59 MSK'::timestamptz;
SELECT '2011-03-27 03:00:00 MSK'::timestamptz;
SELECT '2011-03-27 03:00:01 MSK'::timestamptz;
SELECT '2011-03-27 04:00:00 MSK'::timestamptz;
SELECT '2014-10-26 00:00:00 Europe/Moscow'::timestamptz;
SELECT '2014-10-26 00:59:59 Europe/Moscow'::timestamptz;
SELECT '2014-10-26 01:00:00 Europe/Moscow'::timestamptz;
SELECT '2014-10-26 01:00:01 Europe/Moscow'::timestamptz;
SELECT '2014-10-26 02:00:00 Europe/Moscow'::timestamptz;
SELECT '2014-10-26 00:00:00 MSK'::timestamptz;
SELECT '2014-10-26 00:59:59 MSK'::timestamptz;
SELECT '2014-10-26 01:00:00 MSK'::timestamptz;
SELECT '2014-10-26 01:00:01 MSK'::timestamptz;
SELECT '2014-10-26 02:00:00 MSK'::timestamptz;
SELECT '2011-03-27 00:00:00'::timestamp AT TIME ZONE 'Europe/Moscow';
SELECT '2011-03-27 01:00:00'::timestamp AT TIME ZONE 'Europe/Moscow';
SELECT '2011-03-27 01:59:59'::timestamp AT TIME ZONE 'Europe/Moscow';
SELECT '2011-03-27 02:00:00'::timestamp AT TIME ZONE 'Europe/Moscow';
SELECT '2011-03-27 02:00:01'::timestamp AT TIME ZONE 'Europe/Moscow';
SELECT '2011-03-27 02:59:59'::timestamp AT TIME ZONE 'Europe/Moscow';
SELECT '2011-03-27 03:00:00'::timestamp AT TIME ZONE 'Europe/Moscow';
SELECT '2011-03-27 03:00:01'::timestamp AT TIME ZONE 'Europe/Moscow';
SELECT '2011-03-27 04:00:00'::timestamp AT TIME ZONE 'Europe/Moscow';
SELECT '2011-03-27 00:00:00'::timestamp AT TIME ZONE 'MSK';
SELECT '2011-03-27 01:00:00'::timestamp AT TIME ZONE 'MSK';
SELECT '2011-03-27 01:59:59'::timestamp AT TIME ZONE 'MSK';
SELECT '2011-03-27 02:00:00'::timestamp AT TIME ZONE 'MSK';
SELECT '2011-03-27 02:00:01'::timestamp AT TIME ZONE 'MSK';
SELECT '2011-03-27 02:59:59'::timestamp AT TIME ZONE 'MSK';
SELECT '2011-03-27 03:00:00'::timestamp AT TIME ZONE 'MSK';
SELECT '2011-03-27 03:00:01'::timestamp AT TIME ZONE 'MSK';
SELECT '2011-03-27 04:00:00'::timestamp AT TIME ZONE 'MSK';
SELECT '2014-10-26 00:00:00'::timestamp AT TIME ZONE 'Europe/Moscow';
SELECT '2014-10-26 00:59:59'::timestamp AT TIME ZONE 'Europe/Moscow';
SELECT '2014-10-26 01:00:00'::timestamp AT TIME ZONE 'Europe/Moscow';
SELECT '2014-10-26 01:00:01'::timestamp AT TIME ZONE 'Europe/Moscow';
SELECT '2014-10-26 02:00:00'::timestamp AT TIME ZONE 'Europe/Moscow';
SELECT '2014-10-26 00:00:00'::timestamp AT TIME ZONE 'MSK';
SELECT '2014-10-26 00:59:59'::timestamp AT TIME ZONE 'MSK';
SELECT '2014-10-26 01:00:00'::timestamp AT TIME ZONE 'MSK';
SELECT '2014-10-26 01:00:01'::timestamp AT TIME ZONE 'MSK';
SELECT '2014-10-26 02:00:00'::timestamp AT TIME ZONE 'MSK';
SET TimeZone to 'Europe/Moscow';
SELECT '2011-03-26 21:00:00 UTC'::timestamptz;
SELECT '2011-03-26 22:00:00 UTC'::timestamptz;
SELECT '2011-03-26 22:59:59 UTC'::timestamptz;
SELECT '2011-03-26 23:00:00 UTC'::timestamptz;
SELECT '2011-03-26 23:00:01 UTC'::timestamptz;
SELECT '2011-03-26 23:59:59 UTC'::timestamptz;
SELECT '2011-03-27 00:00:00 UTC'::timestamptz;
SELECT '2014-10-25 21:00:00 UTC'::timestamptz;
SELECT '2014-10-25 21:59:59 UTC'::timestamptz;
SELECT '2014-10-25 22:00:00 UTC'::timestamptz;
SELECT '2014-10-25 22:00:01 UTC'::timestamptz;
SELECT '2014-10-25 23:00:00 UTC'::timestamptz;
RESET TimeZone;
SELECT '2011-03-26 21:00:00 UTC'::timestamptz AT TIME ZONE 'Europe/Moscow';
SELECT '2011-03-26 22:00:00 UTC'::timestamptz AT TIME ZONE 'Europe/Moscow';
SELECT '2011-03-26 22:59:59 UTC'::timestamptz AT TIME ZONE 'Europe/Moscow';
SELECT '2011-03-26 23:00:00 UTC'::timestamptz AT TIME ZONE 'Europe/Moscow';
SELECT '2011-03-26 23:00:01 UTC'::timestamptz AT TIME ZONE 'Europe/Moscow';
SELECT '2011-03-26 23:59:59 UTC'::timestamptz AT TIME ZONE 'Europe/Moscow';
SELECT '2011-03-27 00:00:00 UTC'::timestamptz AT TIME ZONE 'Europe/Moscow';
SELECT '2014-10-25 21:00:00 UTC'::timestamptz AT TIME ZONE 'Europe/Moscow';
SELECT '2014-10-25 21:59:59 UTC'::timestamptz AT TIME ZONE 'Europe/Moscow';
SELECT '2014-10-25 22:00:00 UTC'::timestamptz AT TIME ZONE 'Europe/Moscow';
SELECT '2014-10-25 22:00:01 UTC'::timestamptz AT TIME ZONE 'Europe/Moscow';
SELECT '2014-10-25 23:00:00 UTC'::timestamptz AT TIME ZONE 'Europe/Moscow';
SELECT '2011-03-26 21:00:00 UTC'::timestamptz AT TIME ZONE 'MSK';
SELECT '2011-03-26 22:00:00 UTC'::timestamptz AT TIME ZONE 'MSK';
SELECT '2011-03-26 22:59:59 UTC'::timestamptz AT TIME ZONE 'MSK';
SELECT '2011-03-26 23:00:00 UTC'::timestamptz AT TIME ZONE 'MSK';
SELECT '2011-03-26 23:00:01 UTC'::timestamptz AT TIME ZONE 'MSK';
SELECT '2011-03-26 23:59:59 UTC'::timestamptz AT TIME ZONE 'MSK';
SELECT '2011-03-27 00:00:00 UTC'::timestamptz AT TIME ZONE 'MSK';
SELECT '2014-10-25 21:00:00 UTC'::timestamptz AT TIME ZONE 'MSK';
SELECT '2014-10-25 21:59:59 UTC'::timestamptz AT TIME ZONE 'MSK';
SELECT '2014-10-25 22:00:00 UTC'::timestamptz AT TIME ZONE 'MSK';
SELECT '2014-10-25 22:00:01 UTC'::timestamptz AT TIME ZONE 'MSK';
SELECT '2014-10-25 23:00:00 UTC'::timestamptz AT TIME ZONE 'MSK';
--
-- Test that the pg_timezone_names and pg_timezone_abbrevs views are
-- more-or-less working. We can't test their contents in any great detail
-- without the outputs changing anytime IANA updates the underlying data,
-- but it seems reasonable to expect at least one entry per major meridian.
-- (At the time of writing, the actual counts are around 38 because of
-- zones using fractional GMT offsets, so this is a pretty loose test.)
--
select count(distinct utc_offset) >= 24 as ok from pg_timezone_names;
select count(distinct utc_offset) >= 24 as ok from pg_timezone_abbrevs;
-- Let's check the non-default timezone abbreviation sets, too
set timezone_abbreviations = 'Australia';
select count(distinct utc_offset) >= 24 as ok from pg_timezone_abbrevs;
set timezone_abbreviations = 'India';
select count(distinct utc_offset) >= 24 as ok from pg_timezone_abbrevs;