HAWQ-1772. Add INTERVAL_TO_TEXT function
diff --git a/depends/dbcommon/src/dbcommon/function/func-kind.h b/depends/dbcommon/src/dbcommon/function/func-kind.h
index 18ba651..36402ac 100644
--- a/depends/dbcommon/src/dbcommon/function/func-kind.h
+++ b/depends/dbcommon/src/dbcommon/function/func-kind.h
@@ -195,6 +195,7 @@
TEXT_TO_CHAR,
INT_TO_CHAR,
DOUBLE_TO_TIMESTAMP,
+ INTERVAL_TO_TEXT,
// 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 bb1ab0b..06ae53e 100644
--- a/depends/dbcommon/src/dbcommon/function/func.cc
+++ b/depends/dbcommon/src/dbcommon/function/func.cc
@@ -464,6 +464,7 @@
FuncEntryArray.push_back({TEXT_TO_DOUBLE, "text_double", DOUBLEID, {STRINGID}, text_to_float8});
FuncEntryArray.push_back{TEXT_TO_DECIMAL, "text_decimal", DECIMALNEWID, {STRINGID}, textToDecimal});
FuncEntryArray.push_back({TO_NUMBER, "to_number", DECIMALNEWID, {STRINGID, STRINGID}, toNumber});
+ FuncEntryArray.push_back({INTERVAL_TO_TEXT, "interval_text", STRINGID, {INTERVALID}, intervalToText});
FuncEntryArray.push_back({BOOLEAN_TO_SMALLINT, "boolean_smallint", SMALLINTID, {BOOLEANID}, bool_to_int2});
FuncEntryArray.push_back({BOOLEAN_TO_INT, "boolean_int", INTID, {BOOLEANID}, bool_to_int4});
diff --git a/depends/dbcommon/src/dbcommon/function/typecast-texttonum-func.cc b/depends/dbcommon/src/dbcommon/function/typecast-texttonum-func.cc
index 4cd91b4..7a0b20b 100644
--- a/depends/dbcommon/src/dbcommon/function/typecast-texttonum-func.cc
+++ b/depends/dbcommon/src/dbcommon/function/typecast-texttonum-func.cc
@@ -38,6 +38,7 @@
#include "dbcommon/type/type-util.h"
#include "dbcommon/utils/macro.h"
#include "dbcommon/utils/string-util.h"
+#include "dbcommon/utils/timezone-util.h"
namespace dbcommon {
@@ -563,4 +564,128 @@
return text_to_Float<double>(params, size);
}
+Datum intervalToText(Datum *params, uint64_t size) {
+ auto inttotext = [](char *&ptr, uint32_t val) {
+ if (val == 0) {
+ *(ptr++) = '0';
+ return;
+ }
+ char str[] = "0123456789";
+ uint32_t tempval = val;
+ std::vector<char> tempvec;
+ while (tempval >= 10) {
+ tempval /= 10;
+ ++ptr;
+ }
+ char *ptemp = ptr++;
+ while (val > 0) {
+ *(ptemp--) = str[val % 10];
+ val /= 10;
+ }
+ };
+
+ auto intervalCastText = [&inttotext](ByteBuffer &buf,
+ IntervalVar in) -> text {
+ int32_t iyear, imonth, iday;
+ iyear = in.month / MONTHS_PER_YEAR;
+ imonth = in.month % MONTHS_PER_YEAR;
+ iday = in.day;
+
+ int32_t ihour, iminute, isecond, imsecond;
+ ihour = in.timeOffset / USECS_PER_HOUR;
+ in.timeOffset -= ihour * USECS_PER_HOUR;
+ iminute = in.timeOffset / USECS_PER_MINUTE;
+ in.timeOffset -= iminute * USECS_PER_MINUTE;
+ isecond = in.timeOffset / USECS_PER_SEC;
+ imsecond = in.timeOffset - (isecond * USECS_PER_SEC);
+
+ uint32_t lenBefore = buf.size();
+ buf.resize(lenBefore + 128);
+ char *pStart = buf.data() + lenBefore;
+ char *ptemp = buf.data() + lenBefore;
+ bool isBeforeNeg = false;
+ bool isFirst = false;
+ if (iyear) {
+ if (iyear < 0)
+ *(ptemp++) = '-';
+ else if (isBeforeNeg)
+ *(ptemp++) = '+';
+ isBeforeNeg = (iyear < 0);
+ isFirst = true;
+ inttotext(ptemp, abs(iyear));
+ *(ptemp++) = ' ';
+ memcpy(ptemp, "year", 4);
+ ptemp += 4;
+ if (iyear > 1) *(ptemp++) = 's';
+ }
+ if (imonth) {
+ if (isFirst) *(ptemp++) = ' ';
+ isFirst = true;
+ if (imonth < 0)
+ *(ptemp++) = '-';
+ else if (isBeforeNeg)
+ *(ptemp++) = '+';
+ isBeforeNeg = (imonth < 0);
+ inttotext(ptemp, abs(imonth));
+ *(ptemp++) = ' ';
+ memcpy(ptemp, "month", 5);
+ ptemp += 5;
+ if (imonth > 1) *(ptemp++) = 's';
+ }
+ if (iday) {
+ if (isFirst) *(ptemp++) = ' ';
+ isFirst = true;
+ if (iday < 0)
+ *(ptemp++) = '-';
+ else if (isBeforeNeg)
+ *(ptemp++) = '+';
+ isBeforeNeg = (iday < 0);
+ inttotext(ptemp, abs(iday));
+ *(ptemp++) = ' ';
+ memcpy(ptemp, "day", 3);
+ ptemp += 3;
+ if (abs(iday) > 1) *(ptemp++) = 's';
+ }
+ if (ihour || iminute || isecond || imsecond) {
+ if (isFirst) *(ptemp++) = ' ';
+ isFirst = true;
+ if (ihour < 0 || iminute < 0 || isecond < 0 || imsecond < 0)
+ *(ptemp++) = '-';
+ else if (isBeforeNeg)
+ *(ptemp++) = '+';
+ ihour = abs(ihour);
+ iminute = abs(iminute);
+ isecond = abs(isecond);
+ imsecond = abs(imsecond);
+ if (ihour < 10) *(ptemp++) = '0';
+ inttotext(ptemp, ihour);
+ *(ptemp++) = ':';
+ if (iminute < 10) *(ptemp++) = '0';
+ inttotext(ptemp, iminute);
+ *(ptemp++) = ':';
+ if (isecond < 10) *(ptemp++) = '0';
+ inttotext(ptemp, isecond);
+
+ if (imsecond) {
+ int64_t power_of_ten = 100000;
+ *(ptemp++) = '.';
+ while (imsecond / power_of_ten == 0) {
+ *(ptemp++) = '0';
+ power_of_ten /= 10;
+ }
+ while (imsecond % 10 == 0) {
+ imsecond /= 10;
+ }
+ inttotext(ptemp, imsecond);
+ }
+ }
+ int32_t curLen = ptemp - pStart;
+ buf.resize(lenBefore + curLen);
+
+ return text(nullptr, curLen);
+ };
+
+ return one_param_bind<text, IntervalVar>(params, size, intervalCastText);
+}
+
} // namespace dbcommon
diff --git a/depends/dbcommon/src/dbcommon/function/typecast-texttonum-func.h b/depends/dbcommon/src/dbcommon/function/typecast-texttonum-func.h
index beddb3b..ac24e63 100644
--- a/depends/dbcommon/src/dbcommon/function/typecast-texttonum-func.h
+++ b/depends/dbcommon/src/dbcommon/function/typecast-texttonum-func.h
@@ -33,6 +33,7 @@
Datum text_to_float8(Datum *params, uint64_t size);
Datum textToDecimal(Datum *params, uint64_t size);
Datum toNumber(Datum *params, uint64_t size);
+Datum intervalToText(Datum *params, uint64_t size);
} // namespace dbcommon
diff --git a/depends/dbcommon/test/unit/function/test-typecast-texttonum-func.cc b/depends/dbcommon/test/unit/function/test-typecast-texttonum-func.cc
index e9fae7c..7d81e12 100644
--- a/depends/dbcommon/test/unit/function/test-typecast-texttonum-func.cc
+++ b/depends/dbcommon/test/unit/function/test-typecast-texttonum-func.cc
@@ -104,4 +104,12 @@
"e33 1.23eq2 1.2i3e2 1.23e2i2"},
ERRCODE_INVALID_TEXT_REPRESENTATION}));
+INSTANTIATE_TEST_CASE_P(
+ interval_to_text, TestFunction,
+ ::testing::Values(TestFunctionEntry{
+ FuncKind::INTERVAL_TO_TEXT,
+ "Vector{delimiter=x}: 4 years 2 months 560 days 00:00:30x-4 year -2 "
+ "month +560 days 00:00:00.003xNULL",
+ {"Vector: 50:560:30000000 -50:560:3000 NULL"}}));
+
} // namespace dbcommon