You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-07-29 08:21:15 +03:00
MCOL-4171 Window functions with decimal(38)
This commit is contained in:
committed by
Roman Nozdrin
parent
62c1c1e0e2
commit
c4d8516a47
@ -24,6 +24,7 @@
|
|||||||
#include "calpontsystemcatalog.h"
|
#include "calpontsystemcatalog.h"
|
||||||
|
|
||||||
using int128_t = __int128;
|
using int128_t = __int128;
|
||||||
|
using uint128_t = unsigned __int128;
|
||||||
using ColTypeAlias = execplan::CalpontSystemCatalog::ColType;
|
using ColTypeAlias = execplan::CalpontSystemCatalog::ColType;
|
||||||
using ColDataTypeAlias = execplan::CalpontSystemCatalog::ColDataType;
|
using ColDataTypeAlias = execplan::CalpontSystemCatalog::ColDataType;
|
||||||
|
|
||||||
@ -32,6 +33,45 @@ namespace execplan
|
|||||||
struct IDB_Decimal;
|
struct IDB_Decimal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A class by Fabio Fernandes pulled off of stackoverflow
|
||||||
|
// Creates a type _xxl that can be used to create 128bit constant values
|
||||||
|
// Ex: int128_t i128 = 12345678901234567890123456789_xxl
|
||||||
|
namespace detail_xxl
|
||||||
|
{
|
||||||
|
constexpr uint8_t hexval(char c)
|
||||||
|
{ return c>='a' ? (10+c-'a') : c>='A' ? (10+c-'A') : c-'0'; }
|
||||||
|
|
||||||
|
template <int BASE, uint128_t V>
|
||||||
|
constexpr uint128_t lit_eval() { return V; }
|
||||||
|
|
||||||
|
template <int BASE, uint128_t V, char C, char... Cs>
|
||||||
|
constexpr uint128_t lit_eval() {
|
||||||
|
static_assert( BASE!=16 || sizeof...(Cs) <= 32-1, "Literal too large for BASE=16");
|
||||||
|
static_assert( BASE!=10 || sizeof...(Cs) <= 39-1, "Literal too large for BASE=10");
|
||||||
|
static_assert( BASE!=8 || sizeof...(Cs) <= 44-1, "Literal too large for BASE=8");
|
||||||
|
static_assert( BASE!=2 || sizeof...(Cs) <= 128-1, "Literal too large for BASE=2");
|
||||||
|
return lit_eval<BASE, BASE*V + hexval(C), Cs...>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<char... Cs > struct LitEval
|
||||||
|
{static constexpr uint128_t eval() {return lit_eval<10,0,Cs...>();} };
|
||||||
|
|
||||||
|
template<char... Cs> struct LitEval<'0','x',Cs...>
|
||||||
|
{static constexpr uint128_t eval() {return lit_eval<16,0,Cs...>();} };
|
||||||
|
|
||||||
|
template<char... Cs> struct LitEval<'0','b',Cs...>
|
||||||
|
{static constexpr uint128_t eval() {return lit_eval<2,0,Cs...>();} };
|
||||||
|
|
||||||
|
template<char... Cs> struct LitEval<'0',Cs...>
|
||||||
|
{static constexpr uint128_t eval() {return lit_eval<8,0,Cs...>();} };
|
||||||
|
|
||||||
|
template<char... Cs>
|
||||||
|
constexpr uint128_t operator "" _xxl() {return LitEval<Cs...>::eval();}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<char... Cs>
|
||||||
|
constexpr uint128_t operator "" _xxl() {return ::detail_xxl::operator "" _xxl<Cs...>();}
|
||||||
|
|
||||||
namespace datatypes
|
namespace datatypes
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -65,6 +105,29 @@ const uint64_t mcs_pow_10[20] =
|
|||||||
1000000000000000000ULL,
|
1000000000000000000ULL,
|
||||||
10000000000000000000ULL
|
10000000000000000000ULL
|
||||||
};
|
};
|
||||||
|
const uint128_t mcs_pow_10_128[20] =
|
||||||
|
{
|
||||||
|
10000000000000000000_xxl,
|
||||||
|
100000000000000000000_xxl,
|
||||||
|
1000000000000000000000_xxl,
|
||||||
|
10000000000000000000000_xxl,
|
||||||
|
100000000000000000000000_xxl,
|
||||||
|
1000000000000000000000000_xxl,
|
||||||
|
10000000000000000000000000_xxl,
|
||||||
|
100000000000000000000000000_xxl,
|
||||||
|
1000000000000000000000000000_xxl,
|
||||||
|
10000000000000000000000000000_xxl,
|
||||||
|
100000000000000000000000000000_xxl,
|
||||||
|
1000000000000000000000000000000_xxl,
|
||||||
|
10000000000000000000000000000000_xxl,
|
||||||
|
100000000000000000000000000000000_xxl,
|
||||||
|
1000000000000000000000000000000000_xxl,
|
||||||
|
10000000000000000000000000000000000_xxl,
|
||||||
|
100000000000000000000000000000000000_xxl,
|
||||||
|
1000000000000000000000000000000000000_xxl,
|
||||||
|
10000000000000000000000000000000000000_xxl,
|
||||||
|
100000000000000000000000000000000000000_xxl
|
||||||
|
};
|
||||||
|
|
||||||
constexpr uint32_t maxPowOf10 = sizeof(mcs_pow_10)/sizeof(mcs_pow_10[0])-1;
|
constexpr uint32_t maxPowOf10 = sizeof(mcs_pow_10)/sizeof(mcs_pow_10[0])-1;
|
||||||
constexpr int128_t Decimal128Null = int128_t(0x8000000000000000LL) << 64;
|
constexpr int128_t Decimal128Null = int128_t(0x8000000000000000LL) << 64;
|
||||||
@ -75,21 +138,21 @@ constexpr int128_t Decimal128Empty = (int128_t(0x8000000000000000LL) << 64) + 1;
|
|||||||
@brief The function to produce scale multiplier/divisor for
|
@brief The function to produce scale multiplier/divisor for
|
||||||
wide decimals.
|
wide decimals.
|
||||||
*/
|
*/
|
||||||
inline void getScaleDivisor(int128_t& divisor, const int8_t scale)
|
template<typename T>
|
||||||
|
inline void getScaleDivisor(T& divisor, const int8_t scale)
|
||||||
{
|
{
|
||||||
divisor = 1;
|
if (scale < 0)
|
||||||
switch (scale/maxPowOf10)
|
|
||||||
{
|
{
|
||||||
case 2:
|
std::string msg = "getScaleDivisor called with negative scale: " + std::to_string(scale);
|
||||||
divisor *= mcs_pow_10[maxPowOf10];
|
throw std::invalid_argument(msg);
|
||||||
divisor *= mcs_pow_10[maxPowOf10];
|
}
|
||||||
break;
|
if (scale < 19)
|
||||||
case 1:
|
{
|
||||||
divisor *= mcs_pow_10[maxPowOf10];
|
divisor = mcs_pow_10[scale];
|
||||||
case 0:
|
}
|
||||||
divisor *= mcs_pow_10[scale%maxPowOf10];
|
else
|
||||||
default:
|
{
|
||||||
break;
|
divisor = mcs_pow_10_128[scale-18];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,7 +361,9 @@ bool WindowFunctionColumn::hasWindowFunc()
|
|||||||
|
|
||||||
void WindowFunctionColumn::adjustResultType()
|
void WindowFunctionColumn::adjustResultType()
|
||||||
{
|
{
|
||||||
if (fResultType.colDataType == CalpontSystemCatalog::DECIMAL &&
|
if ((fResultType.colDataType == CalpontSystemCatalog::DECIMAL ||
|
||||||
|
fResultType.colDataType == CalpontSystemCatalog::UDECIMAL)
|
||||||
|
&&
|
||||||
!boost::iequals(fFunctionName, "COUNT") &&
|
!boost::iequals(fFunctionName, "COUNT") &&
|
||||||
!boost::iequals(fFunctionName, "COUNT(*)") &&
|
!boost::iequals(fFunctionName, "COUNT(*)") &&
|
||||||
!boost::iequals(fFunctionName, "ROW_NUMBER") &&
|
!boost::iequals(fFunctionName, "ROW_NUMBER") &&
|
||||||
@ -389,7 +391,8 @@ void WindowFunctionColumn::adjustResultType()
|
|||||||
boost::iequals(fFunctionName, "AVG") ||
|
boost::iequals(fFunctionName, "AVG") ||
|
||||||
boost::iequals(fFunctionName, "AVG_DISTINCT"))
|
boost::iequals(fFunctionName, "AVG_DISTINCT"))
|
||||||
{
|
{
|
||||||
if (fFunctionParms[0]->resultType().colDataType == CalpontSystemCatalog::DECIMAL)
|
if (fFunctionParms[0]->resultType().colDataType == CalpontSystemCatalog::DECIMAL ||
|
||||||
|
fFunctionParms[0]->resultType().colDataType == CalpontSystemCatalog::UDECIMAL)
|
||||||
{
|
{
|
||||||
fResultType.colWidth = sizeof(int128_t);
|
fResultType.colWidth = sizeof(int128_t);
|
||||||
}
|
}
|
||||||
|
@ -380,7 +380,7 @@ public:
|
|||||||
template<int len> inline bool equals(uint64_t val, uint32_t colIndex) const;
|
template<int len> inline bool equals(uint64_t val, uint32_t colIndex) const;
|
||||||
inline bool equals(long double val, uint32_t colIndex) const;
|
inline bool equals(long double val, uint32_t colIndex) const;
|
||||||
bool equals(const std::string& val, uint32_t colIndex) const;
|
bool equals(const std::string& val, uint32_t colIndex) const;
|
||||||
inline bool equals(int128_t val, uint32_t colIndex) const;
|
inline bool equals(const int128_t& val, uint32_t colIndex) const;
|
||||||
|
|
||||||
inline double getDoubleField(uint32_t colIndex) const;
|
inline double getDoubleField(uint32_t colIndex) const;
|
||||||
inline float getFloatField(uint32_t colIndex) const;
|
inline float getFloatField(uint32_t colIndex) const;
|
||||||
@ -709,7 +709,7 @@ inline bool Row::equals(long double val, uint32_t colIndex) const
|
|||||||
return *((long double*) &data[offsets[colIndex]]) == val;
|
return *((long double*) &data[offsets[colIndex]]) == val;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Row::equals(int128_t val, uint32_t colIndex) const
|
inline bool Row::equals(const int128_t& val, uint32_t colIndex) const
|
||||||
{
|
{
|
||||||
return *((int128_t*) &data[offsets[colIndex]]) == val;
|
return *((int128_t*) &data[offsets[colIndex]]) == val;
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,6 @@ using namespace logging;
|
|||||||
using namespace ordering;
|
using namespace ordering;
|
||||||
|
|
||||||
#include "calpontsystemcatalog.h"
|
#include "calpontsystemcatalog.h"
|
||||||
#include "dataconvert.h" // int64_t IDB_pow[19]
|
|
||||||
using namespace execplan;
|
using namespace execplan;
|
||||||
|
|
||||||
#include "windowfunctionstep.h"
|
#include "windowfunctionstep.h"
|
||||||
@ -59,6 +58,7 @@ using namespace joblist;
|
|||||||
#include "wf_stats.h"
|
#include "wf_stats.h"
|
||||||
#include "wf_sum_avg.h"
|
#include "wf_sum_avg.h"
|
||||||
#include "wf_udaf.h"
|
#include "wf_udaf.h"
|
||||||
|
#include "mcs_decimal.h"
|
||||||
|
|
||||||
namespace windowfunction
|
namespace windowfunction
|
||||||
{
|
{
|
||||||
@ -480,7 +480,7 @@ template<typename T>
|
|||||||
void WindowFunctionType::implicit2T(uint64_t i, T& t, int s)
|
void WindowFunctionType::implicit2T(uint64_t i, T& t, int s)
|
||||||
{
|
{
|
||||||
int ct = fRow.getColType(i);
|
int ct = fRow.getColType(i);
|
||||||
int pw = 0;
|
int64_t divisor = 1;
|
||||||
|
|
||||||
switch (ct)
|
switch (ct)
|
||||||
{
|
{
|
||||||
@ -491,13 +491,6 @@ void WindowFunctionType::implicit2T(uint64_t i, T& t, int s)
|
|||||||
case CalpontSystemCatalog::BIGINT:
|
case CalpontSystemCatalog::BIGINT:
|
||||||
{
|
{
|
||||||
t = (T) fRow.getIntField(i);
|
t = (T) fRow.getIntField(i);
|
||||||
pw = s - fRow.getScale(i); // pw is difference of scales, will be in [-18, 18]
|
|
||||||
|
|
||||||
if (pw > 0)
|
|
||||||
t *= IDB_pow[pw];
|
|
||||||
else if (pw < 0)
|
|
||||||
t /= IDB_pow[-pw];
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,13 +501,6 @@ void WindowFunctionType::implicit2T(uint64_t i, T& t, int s)
|
|||||||
case CalpontSystemCatalog::UBIGINT:
|
case CalpontSystemCatalog::UBIGINT:
|
||||||
{
|
{
|
||||||
t = (T) fRow.getUintField(i);
|
t = (T) fRow.getUintField(i);
|
||||||
pw = s - fRow.getScale(i); // pw is difference of scales, will be in [-18, 18]
|
|
||||||
|
|
||||||
if (pw > 0)
|
|
||||||
t *= IDB_pow[pw];
|
|
||||||
else if (pw < 0)
|
|
||||||
t /= IDB_pow[-pw];
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,13 +511,6 @@ void WindowFunctionType::implicit2T(uint64_t i, T& t, int s)
|
|||||||
t = (T) fRow.getIntField(i);
|
t = (T) fRow.getIntField(i);
|
||||||
else
|
else
|
||||||
t = (T) fRow.getInt128Field(i);
|
t = (T) fRow.getInt128Field(i);
|
||||||
pw = s - fRow.getScale(i); // pw is difference of scales, will be in [-18, 18]
|
|
||||||
|
|
||||||
if (pw > 0)
|
|
||||||
t *= IDB_pow[pw];
|
|
||||||
else if (pw < 0)
|
|
||||||
t /= IDB_pow[-pw];
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -542,45 +521,26 @@ void WindowFunctionType::implicit2T(uint64_t i, T& t, int s)
|
|||||||
t = (T) fRow.getUintField(i);
|
t = (T) fRow.getUintField(i);
|
||||||
else
|
else
|
||||||
t = (T) fRow.getUint128Field(i);
|
t = (T) fRow.getUint128Field(i);
|
||||||
pw = s - fRow.getScale(i); // pw is difference of scales, will be in [-18, 18]
|
|
||||||
|
|
||||||
if (pw > 0)
|
|
||||||
t *= IDB_pow[pw];
|
|
||||||
else if (pw < 0)
|
|
||||||
t /= IDB_pow[-pw];
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CalpontSystemCatalog::DOUBLE:
|
case CalpontSystemCatalog::DOUBLE:
|
||||||
case CalpontSystemCatalog::UDOUBLE:
|
case CalpontSystemCatalog::UDOUBLE:
|
||||||
{
|
{
|
||||||
if (s == 0)
|
t = (T) fRow.getDoubleField(i);
|
||||||
t = (T) fRow.getDoubleField(i);
|
|
||||||
else
|
|
||||||
t = (T) (fRow.getDoubleField(i) * IDB_pow[s]); // s is scale, [0, 18]
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CalpontSystemCatalog::FLOAT:
|
case CalpontSystemCatalog::FLOAT:
|
||||||
case CalpontSystemCatalog::UFLOAT:
|
case CalpontSystemCatalog::UFLOAT:
|
||||||
{
|
{
|
||||||
if (s == 0)
|
t = (T) fRow.getFloatField(i);
|
||||||
t = (T) fRow.getFloatField(i);
|
|
||||||
else
|
|
||||||
t = (T) (fRow.getFloatField(i) * IDB_pow[s]); // s is scale, [0, 18]
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CalpontSystemCatalog::LONGDOUBLE:
|
case CalpontSystemCatalog::LONGDOUBLE:
|
||||||
{
|
{
|
||||||
if (s == 0)
|
t = (T) fRow.getLongDoubleField(i);
|
||||||
t = (T) fRow.getLongDoubleField(i);
|
|
||||||
else
|
|
||||||
t = (T) (fRow.getLongDoubleField(i) * IDB_pow[s]); // s is scale, [0, 18]
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -596,6 +556,15 @@ void WindowFunctionType::implicit2T(uint64_t i, T& t, int s)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s -= fRow.getScale(i); // we scale only the difference of scales
|
||||||
|
datatypes::getScaleDivisor(divisor, abs(s));
|
||||||
|
if (s > 0)
|
||||||
|
t *= divisor;
|
||||||
|
else if (s < 0)
|
||||||
|
t /= divisor;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
Reference in New Issue
Block a user