diff --git a/mysql-test/columnstore/basic/r/mcs70_cast_date_time.result b/mysql-test/columnstore/basic/r/mcs70_cast_date_time.result index 164aa4abf..d8428eb87 100644 --- a/mysql-test/columnstore/basic/r/mcs70_cast_date_time.result +++ b/mysql-test/columnstore/basic/r/mcs70_cast_date_time.result @@ -46,6 +46,6 @@ SELECT CAST(t1_time AS DECIMAL(32,6)), CAST(t1_date AS DECIMAL(32,6)), CAST(t1_d CAST(t1_time AS DECIMAL(32,6)) CAST(t1_date AS DECIMAL(32,6)) CAST(t1_datetime AS DECIMAL(32,6)) NULL NULL NULL 0.000000 0.000000 0.000000 -220816000000.000000 20201111.000000 20201111112233.000000 -200732000000.000000 22220101.000000 22220101102030.000000 +112233.000000 20201111.000000 20201111112233.000000 +102030.000000 22220101.000000 22220101102030.000000 DROP DATABASE mcs70_db; diff --git a/utils/dataconvert/dataconvert.cpp b/utils/dataconvert/dataconvert.cpp index fefca375f..c4cc52c29 100644 --- a/utils/dataconvert/dataconvert.cpp +++ b/utils/dataconvert/dataconvert.cpp @@ -2312,16 +2312,16 @@ std::string DataConvert::timestampToString1(long long timestampvalue, long timez return buf; } -std::string DataConvert::timeToString1(long long datetimevalue) +std::string DataConvert::timeToString1(long long timevalue) { // @bug 4703 abandon multiple ostringstream's for conversion - DateTime dt(datetimevalue); - const int TIMETOSTRING1_LEN = 14; // HHMMSSmmmmmm\0 + Time t(timevalue); + const int TIMETOSTRING1_LEN = 22; // HHMMSSmmmmmm\0 char buf[TIMETOSTRING1_LEN]; char* outbuf = buf; - sprintf(outbuf, "%02d%02d%02d%06d", dt.hour, dt.minute, dt.second, dt.msecond); + sprintf(outbuf, "%02d%02d%02d%06d", t.hour, t.minute, t.second, t.msecond); return buf; } diff --git a/utils/funcexp/func_cast.cpp b/utils/funcexp/func_cast.cpp index 98a2aec76..e88109cd0 100644 --- a/utils/funcexp/func_cast.cpp +++ b/utils/funcexp/func_cast.cpp @@ -1372,7 +1372,7 @@ IDB_Decimal Func_cast_decimal::getDecimalVal(Row& row, FunctionParm& parm, bool& string value = dataconvert::DataConvert::timeToString1(parm[0]->data()->getTimeIntVal(row, isNull)); // strip off micro seconds - string date = value.substr(0, 14); + string date = value.substr(0, 6); int64_t x = atoll(date.c_str()); diff --git a/utils/funcexp/func_ceil.cpp b/utils/funcexp/func_ceil.cpp index e5c1f8728..1414d36aa 100644 --- a/utils/funcexp/func_ceil.cpp +++ b/utils/funcexp/func_ceil.cpp @@ -50,6 +50,22 @@ CalpontSystemCatalog::ColType Func_ceil::operationType(FunctionParm& fp, return fp[0]->data()->resultType(); } +inline int64_t ceilDateTime(Row& row, FunctionParm& parm, bool& isNull) +{ + // the following is to handle the case of ceil(datetime), the last 20 bits are the miliseconds, the -1 is to make sure it could round up + return parm[0]->data()->getDatetimeIntVal(row, isNull) + 0xffffe; +} +inline int64_t ceilTimeStamp(Row& row, FunctionParm& parm, bool& isNull) +{ + // the following is to handle the case of ceil(timestamp), the last 20 bits are the miliseconds, the -1 is to make sure it could round up + return parm[0]->data()->getTimestampIntVal(row, isNull) + 0xffffe; +} +inline int64_t ceilTime(Row& row, FunctionParm& parm, bool& isNull) +{ + // the following is to handle the case of ceil(time), the last 24 bits are the miliseconds, the -1 is to make sure it could round up + return parm[0]->data()->getTimeIntVal(row, isNull) + 0xfffffe; +} + int64_t Func_ceil::getIntVal(Row& row, FunctionParm& parm, bool& isNull, CalpontSystemCatalog::ColType& op_ct) { int64_t ret = 0; @@ -147,19 +163,19 @@ int64_t Func_ceil::getIntVal(Row& row, FunctionParm& parm, bool& isNull, Calpont case CalpontSystemCatalog::DATETIME: { - ret = parm[0]->data()->getDatetimeIntVal(row, isNull); + ret = ceilDateTime(row, parm, isNull); } break; case CalpontSystemCatalog::TIMESTAMP: { - ret = parm[0]->data()->getTimestampIntVal(row, isNull); + ret = ceilTimeStamp(row, parm, isNull); } break; case CalpontSystemCatalog::TIME: { - ret = parm[0]->data()->getTimeIntVal(row, isNull); + ret = ceilTime(row, parm, isNull); } break; @@ -272,19 +288,19 @@ uint64_t Func_ceil::getUintVal(Row& row, FunctionParm& parm, bool& isNull, case CalpontSystemCatalog::DATETIME: { - ret = parm[0]->data()->getDatetimeIntVal(row, isNull); + ret = ceilDateTime(row, parm, isNull); } break; case CalpontSystemCatalog::TIMESTAMP: { - ret = parm[0]->data()->getTimestampIntVal(row, isNull); + ret = ceilTimeStamp(row, parm, isNull); } break; case CalpontSystemCatalog::TIME: { - ret = parm[0]->data()->getTimeIntVal(row, isNull); + ret = ceilTime(row, parm, isNull); } break; @@ -559,7 +575,7 @@ IDB_Decimal Func_ceil::getDecimalVal(Row& row, FunctionParm& parm, bool& isNull, case CalpontSystemCatalog::DATETIME: { - DateTime dt(parm[0]->data()->getDatetimeIntVal(row, isNull)); + DateTime dt(ceilDateTime(row, parm, isNull)); if (!isNull) ret.value = dt.convertToMySQLint(); @@ -568,7 +584,7 @@ IDB_Decimal Func_ceil::getDecimalVal(Row& row, FunctionParm& parm, bool& isNull, case CalpontSystemCatalog::TIMESTAMP: { - TimeStamp dt(parm[0]->data()->getTimestampIntVal(row, isNull)); + TimeStamp dt(ceilTimeStamp(row, parm, isNull)); if (!isNull) ret.value = dt.convertToMySQLint(op_ct.getTimeZone()); @@ -577,7 +593,7 @@ IDB_Decimal Func_ceil::getDecimalVal(Row& row, FunctionParm& parm, bool& isNull, case CalpontSystemCatalog::TIME: { - Time dt(parm[0]->data()->getTimeIntVal(row, isNull)); + Time dt(ceilTime(row, parm, isNull)); if (!isNull) ret.value = dt.convertToMySQLint(); diff --git a/utils/funcexp/func_round.cpp b/utils/funcexp/func_round.cpp index 9f265f961..aa8c96ba4 100644 --- a/utils/funcexp/func_round.cpp +++ b/utils/funcexp/func_round.cpp @@ -734,13 +734,49 @@ string Func_round::getStrVal(Row& row, FunctionParm& parm, bool& isNull, Calpont int64_t Func_round::getDatetimeIntVal(Row& row, FunctionParm& parm, bool& isNull, CalpontSystemCatalog::ColType& op_ct) { - return parm[0]->data()->getIntVal(row, isNull); + int32_t s = parm.size() > 1 ? parm[1]->data()->getIntVal(row, isNull) : 0; + if (isNull) + return 0; + s = (s > MAX_MICROSECOND_PRECISION) ? MAX_MICROSECOND_PRECISION : s; + if (s < 0) + { + s = 0; + } + int64_t x = parm[0]->data()->getDatetimeIntVal(row, isNull) + (s <= MAX_MICROSECOND_PRECISION - 1 ? 5 * helpers::powerOf10_c[MAX_MICROSECOND_PRECISION - s - 1] : 0) + (s == 0 ? 48576 : 0); // 48576 = 0xfffff - 1000000; + int32_t m_x = x & 0xfffff; + return (x ^ m_x) | (m_x / helpers::powerOf10_c[MAX_MICROSECOND_PRECISION - s] * helpers::powerOf10_c[MAX_MICROSECOND_PRECISION - s]); } int64_t Func_round::getTimestampIntVal(rowgroup::Row& row, FunctionParm& parm, bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct) { - return parm[0]->data()->getTimestampIntVal(row, isNull); + int32_t s = parm.size() > 1 ? parm[1]->data()->getIntVal(row, isNull) : 0; + if (isNull) + return 0; + s = (s > MAX_MICROSECOND_PRECISION) ? MAX_MICROSECOND_PRECISION : s; + if (s < 0) + { + s = 0; + } + int64_t x = parm[0]->data()->getTimestampIntVal(row, isNull) + (s <= MAX_MICROSECOND_PRECISION - 1 ? 5 * helpers::powerOf10_c[MAX_MICROSECOND_PRECISION - s - 1] : 0) + (s == 0 ? 48576 : 0); // 48576 = 0xfffff - 1000000; + int32_t m_x = x & 0xfffff; + return (x ^ m_x) | (m_x / helpers::powerOf10_c[MAX_MICROSECOND_PRECISION - s] * helpers::powerOf10_c[MAX_MICROSECOND_PRECISION - s]); +} + +int64_t Func_round::getTimeIntVal(rowgroup::Row& row, FunctionParm& parm, bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) +{ + int32_t s = parm.size() > 1 ? parm[1]->data()->getIntVal(row, isNull) : 0; + if (isNull) + return 0; + s = (s > MAX_MICROSECOND_PRECISION) ? MAX_MICROSECOND_PRECISION : s; + if (s < 0) + { + s = 0; + } + int64_t x = parm[0]->data()->getTimeIntVal(row, isNull) + (s <= MAX_MICROSECOND_PRECISION - 1 ? 5 * helpers::powerOf10_c[MAX_MICROSECOND_PRECISION - 1 - s] : 0) + (s == 0 ? 15777215 : 0); // 15777215 = 0xffffff - 1000000; + int32_t m_x = x & 0xffffff; + return (x ^ m_x) | (m_x / helpers::powerOf10_c[MAX_MICROSECOND_PRECISION - s] * helpers::powerOf10_c[MAX_MICROSECOND_PRECISION - s]); } } // namespace funcexp diff --git a/utils/funcexp/func_truncate.cpp b/utils/funcexp/func_truncate.cpp index ac05cbbb7..fe656eed7 100644 --- a/utils/funcexp/func_truncate.cpp +++ b/utils/funcexp/func_truncate.cpp @@ -527,139 +527,61 @@ IDB_Decimal Func_truncate::getDecimalVal(Row& row, FunctionParm& parm, bool& isN } break; + case execplan::CalpontSystemCatalog::TIME: case execplan::CalpontSystemCatalog::DATETIME: - { - int32_t s = 0; - int64_t x = 0; - - string value = DataConvert::datetimeToString1(parm[0]->data()->getDatetimeIntVal(row, isNull)); - - s = parm[1]->data()->getIntVal(row, isNull); - - if (!isNull) - { - // strip off micro seconds - value = value.substr(0, 14); - x = atoll(value.c_str()); - - if (s > 5) - s = 0; - - if (s > 0) - { - x *= helpers::powerOf10_c[s]; - } - else if (s < 0) - { - s = -s; - - if (s >= (int32_t)value.size()) - { - x = 0; - } - else - { - x /= helpers::powerOf10_c[s]; - x *= helpers::powerOf10_c[s]; - } - - s = 0; - } - } - - decimal.value = x; - decimal.scale = s; - } - break; - case execplan::CalpontSystemCatalog::TIMESTAMP: { int32_t s = 0; - int64_t x = 0; - string value = - DataConvert::timestampToString1(parm[0]->data()->getTimestampIntVal(row, isNull), op_ct.getTimeZone()); + string value; + if (op_ct.colDataType == execplan::CalpontSystemCatalog::TIMESTAMP) + value = dataconvert::DataConvert::timestampToString1(parm[0]->data()->getTimestampIntVal(row, isNull), + op_ct.getTimeZone()); + else + value = dataconvert::DataConvert::datetimeToString1(parm[0]->data()->getDatetimeIntVal(row, isNull)); - s = parm[1]->data()->getIntVal(row, isNull); + // strip off micro seconds + value = value.substr(0, 14); - if (!isNull) + if (parm.size() > 1) // truncate(X, D) { - // strip off micro seconds - value = value.substr(0, 14); - x = atoll(value.c_str()); + s = parm[1]->data()->getIntVal(row, isNull); if (s > 5) s = 0; if (s > 0) { - x *= helpers::powerOf10_c[s]; - } - else if (s < 0) - { - s = -s; - - if (s >= (int32_t)value.size()) + for (int i = 0; i < s; i++) { - x = 0; + value = value + "0"; } + } + else + { + if (-s >= (int32_t)value.size()) + value = "0"; else { - x /= helpers::powerOf10_c[s]; - x *= helpers::powerOf10_c[s]; + value = value.substr(0, value.size() + s); + s = -s; + for (int i = 0; i < s; i++) + { + value = value + "0"; + } } s = 0; } } - decimal.value = x; - decimal.scale = s; - } - break; - - case execplan::CalpontSystemCatalog::TIME: - { - int32_t s = 0; - int64_t x = 0; - - string value = DataConvert::timeToString1(parm[0]->data()->getTimeIntVal(row, isNull)); - - s = parm[1]->data()->getIntVal(row, isNull); + int64_t x = atoll(value.c_str()); if (!isNull) { - // strip off micro seconds - value = value.substr(0, 14); - x = atoll(value.c_str()); - - if (s > 5) - s = 0; - - if (s > 0) - { - x *= helpers::powerOf10_c[s]; - } - else if (s < 0) - { - s = -s; - - if (s >= (int32_t)value.size()) - { - x = 0; - } - else - { - x /= helpers::powerOf10_c[s]; - x *= helpers::powerOf10_c[s]; - } - - s = 0; - } + decimal.value = x; + decimal.scale = s; } - - decimal.value = x; - decimal.scale = s; } break; @@ -735,7 +657,50 @@ string Func_truncate::getStrVal(Row& row, FunctionParm& parm, bool& isNull, int64_t Func_truncate::getTimestampIntVal(rowgroup::Row& row, FunctionParm& parm, bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct) { - return parm[0]->data()->getTimestampIntVal(row, isNull); + int32_t s = parm.size() > 1 ? parm[1]->data()->getIntVal(row, isNull) : 0; + if (isNull) + return 0; + s = (s > MAX_MICROSECOND_PRECISION) ? MAX_MICROSECOND_PRECISION : s; + if (s < 0) + { + s = 0; + } + int64_t x = parm[0]->data()->getTimestampIntVal(row, isNull); + int32_t m_x = x & 0xfffff; + return (x ^ m_x) | (m_x / helpers::powerOf10_c[MAX_MICROSECOND_PRECISION - s] * helpers::powerOf10_c[MAX_MICROSECOND_PRECISION - s]); } +int64_t Func_truncate::getDatetimeIntVal(Row& row, FunctionParm& parm, bool& isNull, + CalpontSystemCatalog::ColType& op_ct) +{ + int32_t s = parm.size() > 1 ? parm[1]->data()->getIntVal(row, isNull) : 0; + if (isNull) + return 0; + s = (s > MAX_MICROSECOND_PRECISION) ? MAX_MICROSECOND_PRECISION : s; + if (s < 0) + { + s = 0; + } + int64_t x = parm[0]->data()->getDatetimeIntVal(row, isNull); + int32_t m_x = x & 0xfffff; + return (x ^ m_x) | (m_x / helpers::powerOf10_c[MAX_MICROSECOND_PRECISION - s] * helpers::powerOf10_c[MAX_MICROSECOND_PRECISION - s]); +} + +int64_t Func_truncate::getTimeIntVal(rowgroup::Row& row, FunctionParm& parm, bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct) +{ + int32_t s = parm.size() > 1 ? parm[1]->data()->getIntVal(row, isNull) : 0; + if (isNull) + return 0; + s = (s > MAX_MICROSECOND_PRECISION) ? MAX_MICROSECOND_PRECISION : s; + if (s < 0) + { + s = 0; + } + int64_t x = parm[0]->data()->getTimeIntVal(row, isNull); + int32_t m_x = x & 0xffffff; + return (x ^ m_x) | (m_x / helpers::powerOf10_c[MAX_MICROSECOND_PRECISION - s] * helpers::powerOf10_c[MAX_MICROSECOND_PRECISION - s]); +} + + } // namespace funcexp diff --git a/utils/funcexp/functor.h b/utils/funcexp/functor.h index 1cc73879f..361888ce5 100644 --- a/utils/funcexp/functor.h +++ b/utils/funcexp/functor.h @@ -53,6 +53,8 @@ namespace funcexp // typedef std::vector FunctionParm; typedef std::vector FunctionParm; +constexpr const int32_t MAX_MICROSECOND_PRECISION = 6; + /** @brief Func class */ class Func diff --git a/utils/funcexp/functor_real.h b/utils/funcexp/functor_real.h index 60ccbe5e0..fbdf25964 100644 --- a/utils/funcexp/functor_real.h +++ b/utils/funcexp/functor_real.h @@ -183,6 +183,9 @@ class Func_round : public Func_Real int64_t getTimestampIntVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + + int64_t getTimeIntVal(rowgroup::Row& row, FunctionParm& parm, bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); }; /** @brief Func_truncate class @@ -220,6 +223,12 @@ class Func_truncate : public Func_Real int64_t getTimestampIntVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, execplan::CalpontSystemCatalog::ColType& op_ct); + + int64_t getDatetimeIntVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); + + int64_t getTimeIntVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, + execplan::CalpontSystemCatalog::ColType& op_ct); }; /** @brief Func_ceil class