HAWQ-1771. Add newQE DOUBLE_TO_TIMESTAMP function
diff --git a/depends/dbcommon/src/dbcommon/function/func-kind.h b/depends/dbcommon/src/dbcommon/function/func-kind.h
index 4c1f487..4fbf961 100644
--- a/depends/dbcommon/src/dbcommon/function/func-kind.h
+++ b/depends/dbcommon/src/dbcommon/function/func-kind.h
@@ -194,6 +194,7 @@
DECIMAL_TO_TEXT,
TEXT_TO_CHAR,
INT_TO_CHAR,
+ DOUBLE_TO_TIMESTAMP,
// date/time related functions
DATE_TO_TIMESTAMP,
diff --git a/depends/dbcommon/src/dbcommon/function/func.cc b/depends/dbcommon/src/dbcommon/function/func.cc
index 7a18187..f9222b3 100644
--- a/depends/dbcommon/src/dbcommon/function/func.cc
+++ b/depends/dbcommon/src/dbcommon/function/func.cc
@@ -327,6 +327,7 @@
FuncEntryArray.push_back({DECIMAL_TO_TEXT, "decimal_to_text", STRINGID, {DECIMALNEWID}, decimal_to_text});
FuncEntryArray.push_back({TEXT_TO_CHAR, "text_to_char", TINYINTID, {STRINGID}, text_to_char});
FuncEntryArray.push_back({INT_TO_CHAR, "int4_to_char", TINYINTID, {INTID}, int4_to_char});
+ FuncEntryArray.push_back({DOUBLE_TO_TIMESTAMP, "double_to_timestamp", TIMESTAMPTZID, {DOUBLEID}, double_to_timestamp});
FuncEntryArray.push_back({CHAR_TO_STRING, "char_to_string", STRINGID, {CHARID},char_to_string, false});
FuncEntryArray.push_back({DATE_TO_TIMESTAMP, "date_to_timestamp", TIMESTAMPID, {DATEID}, date_to_timestamp, false});
diff --git a/depends/dbcommon/src/dbcommon/function/typecast-func.cc b/depends/dbcommon/src/dbcommon/function/typecast-func.cc
index 958f13d..43ef097 100644
--- a/depends/dbcommon/src/dbcommon/function/typecast-func.cc
+++ b/depends/dbcommon/src/dbcommon/function/typecast-func.cc
@@ -18,6 +18,7 @@
*/
#include <cmath>
+#include <tuple>
#include <fstream>
//#include <boost/lexical_cast.hpp>
diff --git a/depends/dbcommon/src/dbcommon/function/typecast-function.cc b/depends/dbcommon/src/dbcommon/function/typecast-function.cc
index cb547cc..deee42f 100644
--- a/depends/dbcommon/src/dbcommon/function/typecast-function.cc
+++ b/depends/dbcommon/src/dbcommon/function/typecast-function.cc
@@ -21,6 +21,7 @@
#include <iomanip>
#include <string>
+#include <tuple>
#include <typeinfo>
#include "dbcommon/common/vector-transformer.h"
@@ -225,5 +226,42 @@
Datum float8_to_text(Datum *params, uint64_t size) {
return floattype_to_text<double>(params, size);
}
+inline std::tuple<int64_t, int64_t> double_to_time(double epoch) {
+ int64_t second, nanosecond;
+ second = (int64_t)epoch;
+ nanosecond = (int64_t)((epoch - second) / 1e-6) * 1000;
+ TimezoneUtil::setGMTOffset("PRC");
+ return std::make_tuple(second, nanosecond);
+}
+Datum double_to_timestamp(Datum *params, uint64_t size) {
+ assert(size == 2);
+ Object *para = params[1];
+ if (dynamic_cast<Vector *>(para)) {
+ Vector *retVector = params[0];
+ Vector *srcVector = params[1];
+
+ FixedSizeTypeVectorRawData<double> src(srcVector);
+ retVector->resize(src.plainSize, src.sel, src.nulls);
+ TimestampVectorRawData ret(retVector);
+
+ auto totimestamp = [&](uint64_t plainIdx) {
+ std::tie(ret.seconds[plainIdx], ret.nanoseconds[plainIdx]) =
+ double_to_time(src.values[plainIdx]);
+ };
+ dbcommon::transformVector(ret.plainSize, ret.sel, ret.nulls, totimestamp);
+ } else {
+ Scalar *retScalar = params[0];
+ Scalar *srcScalar = params[1];
+ if (srcScalar->isnull) {
+ retScalar->isnull = true;
+ } else {
+ retScalar->isnull = false;
+ double src = srcScalar->value;
+ Timestamp *ret = retScalar->allocateValue<Timestamp>();
+ std::tie(ret->second, ret->nanosecond) = double_to_time(src);
+ }
+ }
+ return params[0];
+}
} // namespace dbcommon
diff --git a/depends/dbcommon/src/dbcommon/function/typecast-function.h b/depends/dbcommon/src/dbcommon/function/typecast-function.h
index 7171030..b776dd9 100644
--- a/depends/dbcommon/src/dbcommon/function/typecast-function.h
+++ b/depends/dbcommon/src/dbcommon/function/typecast-function.h
@@ -34,6 +34,7 @@
Datum text_to_char(Datum *params, uint64_t size);
Datum int4_to_char(Datum *params, uint64_t size);
Datum decimal_to_text(Datum *params, uint64_t size);
+Datum double_to_timestamp(Datum *params, uint64_t size);
} // namespace dbcommon
diff --git a/depends/dbcommon/src/dbcommon/type/date.h b/depends/dbcommon/src/dbcommon/type/date.h
index 1900631..4a33727 100644
--- a/depends/dbcommon/src/dbcommon/type/date.h
+++ b/depends/dbcommon/src/dbcommon/type/date.h
@@ -37,6 +37,8 @@
#define POSTGRES_EPOCH_JDATE 2451545 /* == date2j(2000, 1, 1) */
#define ORC_TIMESTAMP_EPOCH_JDATE 2457024 /* == date2j(2015, 1, 1) */
#define AD_EPOCH_JDATE 719162 /* == date2j(0001, 1, 1) */
+#define TIMEZONE_ADJUST \
+ -1325491552 /* == date_part('epoch','1927-12-31 23:54:08')*/
const int64_t SECONDS_PER_HOUR = 60 * 60;
const int64_t SECONDS_PER_DAY = SECONDS_PER_HOUR * 24;
@@ -774,6 +776,9 @@
static std::string timezoneToString(int64_t offset) {
int timezone = offset / SECONDS_PER_HOUR;
+ int time = offset - timezone * SECONDS_PER_HOUR;
+ int t_minute = time / 60;
+ int t_second = time % 60;
std::string result = "";
if (timezone < 0) {
result += "-";
@@ -782,6 +787,14 @@
}
if (timezone < 10) result += "0";
result += std::to_string(std::abs(timezone));
+ if (time) {
+ result += ":";
+ if (t_minute > 0 && t_minute < 10) result += "0";
+ result += std::to_string(std::abs(t_minute));
+ result += ":";
+ if (t_second > 0 && t_second < 10) result += "0";
+ result += std::to_string(std::abs(t_second));
+ }
return result;
}
@@ -840,6 +853,10 @@
int32_t timezoneOffset = TimezoneUtil::getGMTOffset(second);
second += timezoneOffset;
+ if (second < timezoneOffset + TIMEZONE_ADJUST) {
+ timezoneOffset += 352;
+ second += 352;
+ }
int32_t days = (int32_t)(second / SECONDS_PER_DAY);
int64_t seconds = second % SECONDS_PER_DAY * 1000000;
if (seconds < 0) {
diff --git a/depends/dbcommon/test/unit/function/test-typecast-function.cc b/depends/dbcommon/test/unit/function/test-typecast-function.cc
index 938db38..e2a8fe7 100644
--- a/depends/dbcommon/test/unit/function/test-typecast-function.cc
+++ b/depends/dbcommon/test/unit/function/test-typecast-function.cc
@@ -291,5 +291,13 @@
TestFunctionEntry{FuncKind::BIGINT_TO_BOOLEAN,
"Vector: t t t f NULL",
{"Vector: 1 3 -2 0 NULL"}}));
+// TEST(TestFunction, double_to_timestamp) {}
+INSTANTIATE_TEST_CASE_P(
+ double_to_timestamp, TestFunction,
+ ::testing::Values(TestFunctionEntry{
+ FuncKind::DOUBLE_TO_TIMESTAMP,
+ "Vector{delimiter=,}: 1927-12-31 23:54:08+08,1973-11-30 "
+ "05:33:09+08,NULL",
+ {"Vector{delimiter=,}: -1325491552,NULL"}}));
} // namespace dbcommon