1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-08-01 06:46:55 +03:00

MCOL-641 sum() now works with DECIMAL(38) columns.

TupleAggregateStep class method and buildAggregateColumn() now properly set result data type.

doSum() now handles DECIMAL(38) in approprate manner.

Low-level null related methods for new binary-based datatypes now handles magic values for
binary-based DT.
This commit is contained in:
drrtuy
2020-01-30 17:27:36 +03:00
committed by Roman Nozdrin
parent 98213c0094
commit 0ff0472842
6 changed files with 164 additions and 38 deletions

View File

@ -3129,13 +3129,30 @@ void TupleAggregateStep::prep2PhasesAggregate(
throw IDBExcept(emsg, ERR_AGGREGATE_TYPE_NOT_SUPPORT); throw IDBExcept(emsg, ERR_AGGREGATE_TYPE_NOT_SUPPORT);
} }
oidsAggPm.push_back(oidsProj[colProj]); // WIP MCOL-641 Replace condition with a
keysAggPm.push_back(aggKey); // dynamic one
typeAggPm.push_back(CalpontSystemCatalog::LONGDOUBLE); if (typeProj[colProj] == CalpontSystemCatalog::DECIMAL
csNumAggPm.push_back(8); && width[colProj] == 16)
scaleAggPm.push_back(0); {
precisionAggPm.push_back(-1); oidsAggPm.push_back(oidsProj[colProj]);
widthAggPm.push_back(sizeof(long double)); keysAggPm.push_back(aggKey);
typeAggPm.push_back(CalpontSystemCatalog::DECIMAL);
scaleAggPm.push_back(0);
// WIP makes this dynamic
precisionAggPm.push_back(38);
widthAggPm.push_back(width[colProj]);
csNumAggPm.push_back(8);
}
else
{
oidsAggPm.push_back(oidsProj[colProj]);
keysAggPm.push_back(aggKey);
typeAggPm.push_back(CalpontSystemCatalog::LONGDOUBLE);
scaleAggPm.push_back(0);
csNumAggPm.push_back(8);
precisionAggPm.push_back(-1);
widthAggPm.push_back(sizeof(long double));
}
colAggPm++; colAggPm++;
} }

View File

@ -4589,7 +4589,6 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
Item_sum* isp = reinterpret_cast<Item_sum*>(item); Item_sum* isp = reinterpret_cast<Item_sum*>(item);
Item** sfitempp = isp->get_orig_args(); Item** sfitempp = isp->get_orig_args();
// Item** sfitempp = isp->arguments();
SRCP parm; SRCP parm;
// @bug4756 // @bug4756
@ -4809,7 +4808,6 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
if ((fc && fc->functionParms().empty()) || !fc) if ((fc && fc->functionParms().empty()) || !fc)
{ {
//ac->aggOp(AggregateColumn::COUNT_ASTERISK);
ReturnedColumn* rc = buildReturnedColumn(sfitemp, gwi, gwi.fatalParseError); ReturnedColumn* rc = buildReturnedColumn(sfitemp, gwi, gwi.fatalParseError);
if (dynamic_cast<ConstantColumn*>(rc)) if (dynamic_cast<ConstantColumn*>(rc))
@ -4896,6 +4894,7 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
// use the first parm for result type. // use the first parm for result type.
parm = ac->aggParms()[0]; parm = ac->aggParms()[0];
// WIP why do we use LONGDOUBLE for AVG?
if (isp->sum_func() == Item_sum::AVG_FUNC || if (isp->sum_func() == Item_sum::AVG_FUNC ||
isp->sum_func() == Item_sum::AVG_DISTINCT_FUNC) isp->sum_func() == Item_sum::AVG_DISTINCT_FUNC)
{ {
@ -4918,10 +4917,20 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
else if (isp->sum_func() == Item_sum::SUM_FUNC || else if (isp->sum_func() == Item_sum::SUM_FUNC ||
isp->sum_func() == Item_sum::SUM_DISTINCT_FUNC) isp->sum_func() == Item_sum::SUM_DISTINCT_FUNC)
{ {
CalpontSystemCatalog::ColType ct = parm->resultType(); // WIP MCOL-641 This fast hack breaks aggregates for
// all float DT's
// UPD it doesn't break b/c actual DT for result type
// is set during JobList creation.
/*CalpontSystemCatalog::ColType ct = parm->resultType();
ct.colDataType = CalpontSystemCatalog::LONGDOUBLE; ct.colDataType = CalpontSystemCatalog::LONGDOUBLE;
ct.colWidth = sizeof(long double); ct.colWidth = sizeof(long double);
ct.precision = -1; ct.precision = -1;*/
CalpontSystemCatalog::ColType ct = parm->resultType();
ct.colDataType = CalpontSystemCatalog::DECIMAL;
ct.colWidth = 16;
ct.precision = 38;
// WIP set the scale if argument is a float-based DT
ct.scale = 0;
ac->resultType(ct); ac->resultType(ct);
} }
else if (isp->sum_func() == Item_sum::STD_FUNC || else if (isp->sum_func() == Item_sum::STD_FUNC ||

View File

@ -1726,7 +1726,7 @@ void BatchPrimitiveProcessor::execute()
if (fe2->evaluate(&fe2In)) if (fe2->evaluate(&fe2In))
{ {
applyMapping(fe2Mapping, fe2In, &fe2Out); applyMapping(fe2Mapping, fe2In, &fe2Out);
cerr << " passed. output row: " << fe2Out.toString() << endl; //cerr << " passed. output row: " << fe2Out.toString() << endl;
fe2Out.setRid (fe2In.getRelRid()); fe2Out.setRid (fe2In.getRelRid());
fe2Output.incRowCount(); fe2Output.incRowCount();
fe2Out.nextRow(); fe2Out.nextRow();

View File

@ -222,6 +222,11 @@ inline string getStringNullValue()
return joblist::CPNULLSTRMARK; return joblist::CPNULLSTRMARK;
} }
inline uint64_t getBinaryNullValue()
{
return joblist::BINARYNULL;
}
} }
@ -413,6 +418,7 @@ void RowAggregation::updateStringMinMax(string val1, string val2, int64_t col, i
inline bool RowAggregation::isNull(const RowGroup* pRowGroup, const Row& row, int64_t col) inline bool RowAggregation::isNull(const RowGroup* pRowGroup, const Row& row, int64_t col)
{ {
/* TODO: Can we replace all of this with a call to row.isNullValue(col)? */ /* TODO: Can we replace all of this with a call to row.isNullValue(col)? */
// WIP MCOL-641 Yes. We can
bool ret = false; bool ret = false;
int colDataType = (pRowGroup->getColTypes())[col]; int colDataType = (pRowGroup->getColTypes())[col];
@ -536,18 +542,7 @@ inline bool RowAggregation::isNull(const RowGroup* pRowGroup, const Row& row, in
case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::DECIMAL:
case execplan::CalpontSystemCatalog::UDECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL:
{ {
int colWidth = pRowGroup->getColumnWidth(col); row.isNullValue(col);
int64_t val = row.getIntField(col);
if (colWidth == 1)
ret = ((uint8_t)val == joblist::TINYINTNULL);
else if (colWidth == 2)
ret = ((uint16_t)val == joblist::SMALLINTNULL);
else if (colWidth == 4)
ret = ((uint32_t)val == joblist::INTNULL);
else
ret = ((uint64_t)val == joblist::BIGINTNULL);
break; break;
} }
@ -1170,7 +1165,20 @@ void RowAggregation::makeAggFieldsNull(Row& row)
case execplan::CalpontSystemCatalog::UDECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL:
{ {
int colWidth = fRowGroupOut->getColumnWidth(colOut); int colWidth = fRowGroupOut->getColumnWidth(colOut);
row.setIntField(getUintNullValue(colDataType, colWidth), colOut); if (colWidth <= 8)
{
row.setIntField(getUintNullValue(colDataType, colWidth), colOut);
}
else
{
// WIP This is only 1st part of the value
uint64_t nullValue = getBinaryNullValue();
uint32_t offset = row.getOffset(colOut);
row.setBinaryField_offset(&nullValue, sizeof(nullValue),
offset);
row.setBinaryField_offset(&nullValue, sizeof(nullValue),
offset+sizeof(nullValue));
}
break; break;
} }
@ -1339,11 +1347,18 @@ void RowAggregation::doMinMax(const Row& rowIn, int64_t colIn, int64_t colOut, i
// Note: NULL value check must be done on UM & PM // Note: NULL value check must be done on UM & PM
// UM may receive NULL values, too. // UM may receive NULL values, too.
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// WIP MCOL-641. This and other methods must be type based to avoid needless mem
// allocation for wide DTs
void RowAggregation::doSum(const Row& rowIn, int64_t colIn, int64_t colOut, int funcType) void RowAggregation::doSum(const Row& rowIn, int64_t colIn, int64_t colOut, int funcType)
{ {
int colDataType = (fRowGroupIn.getColTypes())[colIn]; int colDataType = (fRowGroupIn.getColTypes())[colIn];
long double valIn = 0; long double valIn = 0;
long double valOut = fRow.getLongDoubleField(colOut); bool isWideDataType = false;
void *wideValInPtr = NULL;
// WIP MCOL-641 Probably the width must be taken
// from colOut
uint32_t width = fRowGroupOut->getColumnWidth(colOut);
if (isNull(&fRowGroupIn, rowIn, colIn) == true) if (isNull(&fRowGroupIn, rowIn, colIn) == true)
return; return;
@ -1372,12 +1387,31 @@ void RowAggregation::doSum(const Row& rowIn, int64_t colIn, int64_t colOut, int
case execplan::CalpontSystemCatalog::DECIMAL: case execplan::CalpontSystemCatalog::DECIMAL:
case execplan::CalpontSystemCatalog::UDECIMAL: case execplan::CalpontSystemCatalog::UDECIMAL:
{ {
valIn = rowIn.getIntField(colIn); // WIP MCOL-641 make the size dynamic and use branch prediction cond
double scale = (double)(fRowGroupIn.getScale())[colIn]; isWideDataType = (width) > 8 ? true : false;
if (valIn != 0 && scale > 0) if (!isWideDataType)
{ {
valIn /= pow(10.0, scale); valIn = rowIn.getIntField(colIn);
double scale = (double)(fRowGroupIn.getScale())[colIn];
if (valIn != 0 && scale > 0)
{
valIn /= pow(10.0, scale);
}
} }
else
{
if (colDataType == execplan::CalpontSystemCatalog::DECIMAL)
{
int128_t *dec = rowIn.getBinaryField<int128_t>(colIn);
wideValInPtr = reinterpret_cast<void*>(dec);
}
else
{
uint128_t *dec = rowIn.getBinaryField<uint128_t>(colIn);
wideValInPtr = reinterpret_cast<void*>(dec);
}
}
break; break;
} }
@ -1428,14 +1462,51 @@ void RowAggregation::doSum(const Row& rowIn, int64_t colIn, int64_t colOut, int
break; break;
} }
} }
if (isNull(fRowGroupOut, fRow, colOut)) // WIP MCOL-641
if (!isWideDataType)
{ {
fRow.setLongDoubleField(valIn, colOut); if (isNull(fRowGroupOut, fRow, colOut))
{
fRow.setLongDoubleField(valIn, colOut);
}
else
{
long double valOut = fRow.getLongDoubleField(colOut);
fRow.setLongDoubleField(valIn+valOut, colOut);
}
} }
else else
{ {
fRow.setLongDoubleField(valIn+valOut, colOut); if (colDataType == execplan::CalpontSystemCatalog::DECIMAL)
} {
int128_t *dec = reinterpret_cast<int128_t*>(wideValInPtr);
// WIP MCOL-641 Replace Row::setBinaryField1
if (isNull(fRowGroupOut, fRow, colOut))
{
fRow.setBinaryField1<int128_t>(dec, width, colOut);
}
else
{
int128_t *valOutPtr = fRow.getBinaryField<int128_t>(colOut);
int128_t sum = *valOutPtr + *dec;
fRow.setBinaryField1<int128_t>(&sum, width, colOut);
}
}
else
{
uint128_t *dec = reinterpret_cast<uint128_t*>(wideValInPtr);
if (isNull(fRowGroupOut, fRow, colOut))
{
fRow.setBinaryField1<uint128_t>(dec, width, colOut);
}
else
{
uint128_t *valOutPtr = fRow.getBinaryField<uint128_t>(colOut);
uint128_t sum = *valOutPtr + *dec;
fRow.setBinaryField1<uint128_t>(&sum, width, colOut);
}
}
} // end-of isWideDataType block
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -815,7 +815,6 @@ void Row::initToNull()
default: default:
*((uint64_t*) &data[offsets[i]]) = *((uint64_t*) joblist::CPNULLSTRMARK.c_str()); *((uint64_t*) &data[offsets[i]]) = *((uint64_t*) joblist::CPNULLSTRMARK.c_str());
memset(&data[offsets[i] + 8], 0, len - 8); memset(&data[offsets[i] + 8], 0, len - 8);
//strcpy((char *) &data[offsets[i]], joblist::CPNULLSTRMARK.c_str());
break; break;
} }
@ -846,6 +845,13 @@ void Row::initToNull()
*((int32_t*) &data[offsets[i]]) = static_cast<int32_t>(joblist::INTNULL); *((int32_t*) &data[offsets[i]]) = static_cast<int32_t>(joblist::INTNULL);
break; break;
case 16 :
// WIP MCOL-641
uint64_t *dec = reinterpret_cast<uint64_t*>(&data[offsets[i]]);
+ dec[0] = joblist::BINARYNULL;
+ dec[1] = joblist::BINARYNULL;
break;
default: default:
*((int64_t*) &data[offsets[i]]) = static_cast<int64_t>(joblist::BIGINTNULL); *((int64_t*) &data[offsets[i]]) = static_cast<int64_t>(joblist::BIGINTNULL);
break; break;
@ -1039,13 +1045,15 @@ bool Row::isNullValue(uint32_t colIndex) const
case CalpontSystemCatalog::UDECIMAL: case CalpontSystemCatalog::UDECIMAL:
{ {
uint32_t len = getColumnWidth(colIndex); uint32_t len = getColumnWidth(colIndex);
const uint64_t *dec;
switch (len) switch (len)
{ {
// MCOL-641 WIP // MCOL-641
case 16: case 16:
return (*((int64_t*) &data[offsets[colIndex]]) == static_cast<int64_t>(joblist::BIGINTNULL)); dec = reinterpret_cast<const uint64_t*>(&data[offsets[colIndex]]);
break; return ((dec[0] == joblist::BINARYNULL)
&& (dec[1] == joblist::BINARYNULL));
case 1 : case 1 :
return (data[offsets[colIndex]] == joblist::TINYINTNULL); return (data[offsets[colIndex]] == joblist::TINYINTNULL);

View File

@ -66,6 +66,9 @@ typedef const struct charset_info_st CHARSET_INFO;
// Workaround for my_global.h #define of isnan(X) causing a std::std namespace // Workaround for my_global.h #define of isnan(X) causing a std::std namespace
using int128_t = __int128;
using uint128_t = unsigned __int128;
namespace rowgroup namespace rowgroup
{ {
@ -424,6 +427,10 @@ public:
void setStringField(const std::string& val, uint32_t colIndex); void setStringField(const std::string& val, uint32_t colIndex);
inline void setStringField(const uint8_t*, uint32_t len, uint32_t colIndex); inline void setStringField(const uint8_t*, uint32_t len, uint32_t colIndex);
inline void setBinaryField(const uint8_t* strdata, uint32_t length, uint32_t offset); inline void setBinaryField(const uint8_t* strdata, uint32_t length, uint32_t offset);
template<typename T>
inline void setBinaryField1(T* strdata, uint32_t width, uint32_t colIndex);
template<typename T>
inline void setBinaryField_offset(T* strdata, uint32_t width, uint32_t colIndex);
// support VARBINARY // support VARBINARY
// Add 2-byte length at the CHARSET_INFO*beginning of the field. NULL and zero length field are // Add 2-byte length at the CHARSET_INFO*beginning of the field. NULL and zero length field are
// treated the same, could use one of the length bit to distinguish these two cases. // treated the same, could use one of the length bit to distinguish these two cases.
@ -804,6 +811,20 @@ inline void Row::setBinaryField(const uint8_t* strdata, uint32_t length, uint32_
memcpy(&data[offset], strdata, length); memcpy(&data[offset], strdata, length);
} }
template<typename T>
inline void Row::setBinaryField1(T* value, uint32_t width, uint32_t colIndex)
{
memcpy(&data[offsets[colIndex]], value, width);
}
template<typename T>
inline void Row::setBinaryField_offset(T* value, uint32_t width, uint32_t offset)
{
// WIP
//memcpy(&data[offset], value, width);
*reinterpret_cast<T*>(&data[offset]) = *value;
}
inline void Row::setStringField(const uint8_t* strdata, uint32_t length, uint32_t colIndex) inline void Row::setStringField(const uint8_t* strdata, uint32_t length, uint32_t colIndex)
{ {
uint64_t offset; uint64_t offset;