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))
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;

View File

@ -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;
}

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));
// strip off micro seconds
string date = value.substr(0, 14);
string date = value.substr(0, 6);
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();
}
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();

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,
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

View File

@ -527,140 +527,62 @@ 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);
if (!isNull)
{
// strip off micro seconds
value = value.substr(0, 14);
x = atoll(value.c_str());
if (parm.size() > 1) // truncate(X, D)
{
s = parm[1]->data()->getIntVal(row, isNull);
if (s > 5)
s = 0;
if (s > 0)
{
x *= helpers::powerOf10_c[s];
for (int i = 0; i < s; i++)
{
value = value + "0";
}
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];
if (-s >= (int32_t)value.size())
value = "0";
else
{
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;
}
}
break;
default:
@ -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

View File

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

View File

@ -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