You've already forked mariadb-columnstore-engine
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:
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user