1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-30 19:23:07 +03:00

MCOL-4991 Solving TRUNCATE/ROUND/CEILING functions on TIME/DATETIME/TIMESTAMP

Add getDecimalVal in func_round and func_truncate for getting value while filtering

MCOL-4991 Solving TRUNCATE/ROUND/CEILING functions on TIME/DATETIME/TIMESTAMP

Update func_cast.cpp
This commit is contained in:
MuHe03
2023-03-23 22:42:39 +01:00
committed by MuHe
parent 256691652d
commit d906974abc
8 changed files with 152 additions and 124 deletions

View File

@ -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)) CAST(t1_time AS DECIMAL(32,6)) CAST(t1_date AS DECIMAL(32,6)) CAST(t1_datetime AS DECIMAL(32,6))
NULL NULL NULL NULL NULL NULL
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
220816000000.000000 20201111.000000 20201111112233.000000 112233.000000 20201111.000000 20201111112233.000000
200732000000.000000 22220101.000000 22220101102030.000000 102030.000000 22220101.000000 22220101102030.000000
DROP DATABASE mcs70_db; DROP DATABASE mcs70_db;

View File

@ -2312,16 +2312,16 @@ std::string DataConvert::timestampToString1(long long timestampvalue, long timez
return buf; return buf;
} }
std::string DataConvert::timeToString1(long long datetimevalue) std::string DataConvert::timeToString1(long long timevalue)
{ {
// @bug 4703 abandon multiple ostringstream's for conversion // @bug 4703 abandon multiple ostringstream's for conversion
DateTime dt(datetimevalue); Time t(timevalue);
const int TIMETOSTRING1_LEN = 14; // HHMMSSmmmmmm\0 const int TIMETOSTRING1_LEN = 22; // HHMMSSmmmmmm\0
char buf[TIMETOSTRING1_LEN]; char buf[TIMETOSTRING1_LEN];
char* outbuf = buf; 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; return buf;
} }

View File

@ -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)); string value = dataconvert::DataConvert::timeToString1(parm[0]->data()->getTimeIntVal(row, isNull));
// strip off micro seconds // strip off micro seconds
string date = value.substr(0, 14); string date = value.substr(0, 6);
int64_t x = atoll(date.c_str()); int64_t x = atoll(date.c_str());

View File

@ -50,6 +50,22 @@ CalpontSystemCatalog::ColType Func_ceil::operationType(FunctionParm& fp,
return fp[0]->data()->resultType(); 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 Func_ceil::getIntVal(Row& row, FunctionParm& parm, bool& isNull, CalpontSystemCatalog::ColType& op_ct)
{ {
int64_t ret = 0; int64_t ret = 0;
@ -147,19 +163,19 @@ int64_t Func_ceil::getIntVal(Row& row, FunctionParm& parm, bool& isNull, Calpont
case CalpontSystemCatalog::DATETIME: case CalpontSystemCatalog::DATETIME:
{ {
ret = parm[0]->data()->getDatetimeIntVal(row, isNull); ret = ceilDateTime(row, parm, isNull);
} }
break; break;
case CalpontSystemCatalog::TIMESTAMP: case CalpontSystemCatalog::TIMESTAMP:
{ {
ret = parm[0]->data()->getTimestampIntVal(row, isNull); ret = ceilTimeStamp(row, parm, isNull);
} }
break; break;
case CalpontSystemCatalog::TIME: case CalpontSystemCatalog::TIME:
{ {
ret = parm[0]->data()->getTimeIntVal(row, isNull); ret = ceilTime(row, parm, isNull);
} }
break; break;
@ -272,19 +288,19 @@ uint64_t Func_ceil::getUintVal(Row& row, FunctionParm& parm, bool& isNull,
case CalpontSystemCatalog::DATETIME: case CalpontSystemCatalog::DATETIME:
{ {
ret = parm[0]->data()->getDatetimeIntVal(row, isNull); ret = ceilDateTime(row, parm, isNull);
} }
break; break;
case CalpontSystemCatalog::TIMESTAMP: case CalpontSystemCatalog::TIMESTAMP:
{ {
ret = parm[0]->data()->getTimestampIntVal(row, isNull); ret = ceilTimeStamp(row, parm, isNull);
} }
break; break;
case CalpontSystemCatalog::TIME: case CalpontSystemCatalog::TIME:
{ {
ret = parm[0]->data()->getTimeIntVal(row, isNull); ret = ceilTime(row, parm, isNull);
} }
break; break;
@ -559,7 +575,7 @@ IDB_Decimal Func_ceil::getDecimalVal(Row& row, FunctionParm& parm, bool& isNull,
case CalpontSystemCatalog::DATETIME: case CalpontSystemCatalog::DATETIME:
{ {
DateTime dt(parm[0]->data()->getDatetimeIntVal(row, isNull)); DateTime dt(ceilDateTime(row, parm, isNull));
if (!isNull) if (!isNull)
ret.value = dt.convertToMySQLint(); ret.value = dt.convertToMySQLint();
@ -568,7 +584,7 @@ IDB_Decimal Func_ceil::getDecimalVal(Row& row, FunctionParm& parm, bool& isNull,
case CalpontSystemCatalog::TIMESTAMP: case CalpontSystemCatalog::TIMESTAMP:
{ {
TimeStamp dt(parm[0]->data()->getTimestampIntVal(row, isNull)); TimeStamp dt(ceilTimeStamp(row, parm, isNull));
if (!isNull) if (!isNull)
ret.value = dt.convertToMySQLint(op_ct.getTimeZone()); 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: case CalpontSystemCatalog::TIME:
{ {
Time dt(parm[0]->data()->getTimeIntVal(row, isNull)); Time dt(ceilTime(row, parm, isNull));
if (!isNull) if (!isNull)
ret.value = dt.convertToMySQLint(); ret.value = dt.convertToMySQLint();

View File

@ -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, int64_t Func_round::getDatetimeIntVal(Row& row, FunctionParm& parm, bool& isNull,
CalpontSystemCatalog::ColType& op_ct) 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, int64_t Func_round::getTimestampIntVal(rowgroup::Row& row, FunctionParm& parm, bool& isNull,
execplan::CalpontSystemCatalog::ColType& op_ct) 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 } // namespace funcexp

View File

@ -527,139 +527,61 @@ IDB_Decimal Func_truncate::getDecimalVal(Row& row, FunctionParm& parm, bool& isN
} }
break; break;
case execplan::CalpontSystemCatalog::TIME:
case execplan::CalpontSystemCatalog::DATETIME: 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: case execplan::CalpontSystemCatalog::TIMESTAMP:
{ {
int32_t s = 0; int32_t s = 0;
int64_t x = 0;
string value = string value;
DataConvert::timestampToString1(parm[0]->data()->getTimestampIntVal(row, isNull), op_ct.getTimeZone()); 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 s = parm[1]->data()->getIntVal(row, isNull);
value = value.substr(0, 14);
x = atoll(value.c_str());
if (s > 5) if (s > 5)
s = 0; s = 0;
if (s > 0) if (s > 0)
{ {
x *= helpers::powerOf10_c[s]; for (int i = 0; i < s; i++)
}
else if (s < 0)
{
s = -s;
if (s >= (int32_t)value.size())
{ {
x = 0; value = value + "0";
} }
}
else
{
if (-s >= (int32_t)value.size())
value = "0";
else else
{ {
x /= helpers::powerOf10_c[s]; value = value.substr(0, value.size() + s);
x *= helpers::powerOf10_c[s]; s = -s;
for (int i = 0; i < s; i++)
{
value = value + "0";
}
} }
s = 0; s = 0;
} }
} }
decimal.value = x; int64_t x = atoll(value.c_str());
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);
if (!isNull) if (!isNull)
{ {
// strip off micro seconds decimal.value = x;
value = value.substr(0, 14); decimal.scale = s;
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; 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, int64_t Func_truncate::getTimestampIntVal(rowgroup::Row& row, FunctionParm& parm, bool& isNull,
execplan::CalpontSystemCatalog::ColType& op_ct) 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 } // namespace funcexp

View File

@ -53,6 +53,8 @@ namespace funcexp
// typedef std::vector<execplan::STNP> FunctionParm; // typedef std::vector<execplan::STNP> FunctionParm;
typedef std::vector<execplan::SPTP> FunctionParm; typedef std::vector<execplan::SPTP> FunctionParm;
constexpr const int32_t MAX_MICROSECOND_PRECISION = 6;
/** @brief Func class /** @brief Func class
*/ */
class Func class Func

View File

@ -183,6 +183,9 @@ class Func_round : public Func_Real
int64_t getTimestampIntVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, int64_t getTimestampIntVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull,
execplan::CalpontSystemCatalog::ColType& op_ct); execplan::CalpontSystemCatalog::ColType& op_ct);
int64_t getTimeIntVal(rowgroup::Row& row, FunctionParm& parm, bool& isNull,
execplan::CalpontSystemCatalog::ColType& op_ct);
}; };
/** @brief Func_truncate class /** @brief Func_truncate class
@ -220,6 +223,12 @@ class Func_truncate : public Func_Real
int64_t getTimestampIntVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull, int64_t getTimestampIntVal(rowgroup::Row& row, FunctionParm& fp, bool& isNull,
execplan::CalpontSystemCatalog::ColType& op_ct); 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 /** @brief Func_ceil class