1
0
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:
David Hall
2020-08-10 13:59:49 -05:00
committed by Roman Nozdrin
parent 62c1c1e0e2
commit c4d8516a47
4 changed files with 97 additions and 62 deletions

View File

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

View File

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

View File

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

View File

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