1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-30 19:23:07 +03:00

MCOL-926 Handle NULLs better for UDAF

This commit is contained in:
David Hall
2017-10-04 11:04:10 -05:00
parent f46650ffde
commit 9b6accbdea
2 changed files with 88 additions and 74 deletions

View File

@ -1850,71 +1850,74 @@ void RowAggregation::doUDAF(const Row& rowIn, int64_t colIn, int64_t colOut, int
mcsv1sdk::ColumnDatum datum; mcsv1sdk::ColumnDatum datum;
switch (colDataType) if (!rgContext.isParamNull(0))
{ {
case execplan::CalpontSystemCatalog::TINYINT: switch (colDataType)
case execplan::CalpontSystemCatalog::SMALLINT:
case execplan::CalpontSystemCatalog::MEDINT:
case execplan::CalpontSystemCatalog::INT:
case execplan::CalpontSystemCatalog::BIGINT:
case execplan::CalpontSystemCatalog::DECIMAL:
case execplan::CalpontSystemCatalog::UDECIMAL:
{ {
datum.dataType = execplan::CalpontSystemCatalog::BIGINT; case execplan::CalpontSystemCatalog::TINYINT:
datum.columnData = rowIn.getIntField(colIn); case execplan::CalpontSystemCatalog::SMALLINT:
datum.scale = fRowGroupIn.getScale()[colIn]; case execplan::CalpontSystemCatalog::MEDINT:
datum.precision = fRowGroupIn.getPrecision()[colIn]; case execplan::CalpontSystemCatalog::INT:
break; case execplan::CalpontSystemCatalog::BIGINT:
} case execplan::CalpontSystemCatalog::DECIMAL:
case execplan::CalpontSystemCatalog::UTINYINT: case execplan::CalpontSystemCatalog::UDECIMAL:
case execplan::CalpontSystemCatalog::USMALLINT: {
case execplan::CalpontSystemCatalog::UMEDINT: datum.dataType = execplan::CalpontSystemCatalog::BIGINT;
case execplan::CalpontSystemCatalog::UINT: datum.columnData = rowIn.getIntField(colIn);
case execplan::CalpontSystemCatalog::UBIGINT: datum.scale = fRowGroupIn.getScale()[colIn];
{ datum.precision = fRowGroupIn.getPrecision()[colIn];
datum.dataType = execplan::CalpontSystemCatalog::UBIGINT; break;
datum.columnData = rowIn.getUintField(colIn); }
break; case execplan::CalpontSystemCatalog::UTINYINT:
} case execplan::CalpontSystemCatalog::USMALLINT:
case execplan::CalpontSystemCatalog::DOUBLE: case execplan::CalpontSystemCatalog::UMEDINT:
case execplan::CalpontSystemCatalog::UDOUBLE: case execplan::CalpontSystemCatalog::UINT:
{ case execplan::CalpontSystemCatalog::UBIGINT:
datum.dataType = execplan::CalpontSystemCatalog::DOUBLE; {
datum.columnData = rowIn.getDoubleField(colIn); datum.dataType = execplan::CalpontSystemCatalog::UBIGINT;
break; datum.columnData = rowIn.getUintField(colIn);
} break;
case execplan::CalpontSystemCatalog::FLOAT: }
case execplan::CalpontSystemCatalog::UFLOAT: case execplan::CalpontSystemCatalog::DOUBLE:
{ case execplan::CalpontSystemCatalog::UDOUBLE:
datum.dataType = execplan::CalpontSystemCatalog::FLOAT; {
datum.columnData = rowIn.getFloatField(colIn); datum.dataType = execplan::CalpontSystemCatalog::DOUBLE;
break; datum.columnData = rowIn.getDoubleField(colIn);
} break;
case execplan::CalpontSystemCatalog::DATE: }
case execplan::CalpontSystemCatalog::DATETIME: case execplan::CalpontSystemCatalog::FLOAT:
{ case execplan::CalpontSystemCatalog::UFLOAT:
datum.dataType = execplan::CalpontSystemCatalog::UBIGINT; {
datum.columnData = rowIn.getUintField(colIn); datum.dataType = execplan::CalpontSystemCatalog::FLOAT;
break; datum.columnData = rowIn.getFloatField(colIn);
} break;
case execplan::CalpontSystemCatalog::CHAR: }
case execplan::CalpontSystemCatalog::VARCHAR: case execplan::CalpontSystemCatalog::DATE:
case execplan::CalpontSystemCatalog::TEXT: case execplan::CalpontSystemCatalog::DATETIME:
case execplan::CalpontSystemCatalog::VARBINARY: {
case execplan::CalpontSystemCatalog::CLOB: datum.dataType = execplan::CalpontSystemCatalog::UBIGINT;
case execplan::CalpontSystemCatalog::BLOB: datum.columnData = rowIn.getUintField(colIn);
{ break;
datum.dataType = colDataType; }
datum.columnData = rowIn.getStringField(colIn); case execplan::CalpontSystemCatalog::CHAR:
break; case execplan::CalpontSystemCatalog::VARCHAR:
} case execplan::CalpontSystemCatalog::TEXT:
default: case execplan::CalpontSystemCatalog::VARBINARY:
{ case execplan::CalpontSystemCatalog::CLOB:
std::ostringstream errmsg; case execplan::CalpontSystemCatalog::BLOB:
errmsg << "RowAggregation " << rgContext.getName() << {
": No logic for data type: " << colDataType; datum.dataType = colDataType;
throw logging::QueryDataExcept(errmsg.str(), logging::aggregateFuncErr); datum.columnData = rowIn.getStringField(colIn);
break; break;
}
default:
{
std::ostringstream errmsg;
errmsg << "RowAggregation " << rgContext.getName() <<
": No logic for data type: " << colDataType;
throw logging::QueryDataExcept(errmsg.str(), logging::aggregateFuncErr);
break;
}
} }
} }
valsIn.push_back(datum); valsIn.push_back(datum);
@ -3720,11 +3723,22 @@ void RowAggregationUMP2::doUDAF(const Row& rowIn, int64_t colIn, int64_t colOut,
static_any::any valOut; static_any::any valOut;
mcsv1sdk::mcsv1Context rgContext(rowUDAF->fUDAFContext); mcsv1sdk::mcsv1Context rgContext(rowUDAF->fUDAFContext);
// Turn on NULL flags // Get the user data
boost::shared_ptr<mcsv1sdk::UserData> userData = rowIn.getUserData(colIn+1);
// Unlike other aggregates, the data isn't in colIn, so testing it for NULL
// there won't help. In case of NULL, userData will be NULL.
std::vector<uint32_t> flags; std::vector<uint32_t> flags;
uint32_t flag = 0; uint32_t flag = 0;
if (isNull(&fRowGroupIn, rowIn, colIn) == true) if (!userData)
{
if (rgContext.getRunFlag(mcsv1sdk::UDAF_IGNORE_NULLS))
{
return;
}
// Turn on NULL flags
flag |= mcsv1sdk::PARAM_IS_NULL; flag |= mcsv1sdk::PARAM_IS_NULL;
}
flags.push_back(flag); flags.push_back(flag);
rgContext.setDataFlags(&flags); rgContext.setDataFlags(&flags);
@ -3733,12 +3747,6 @@ void RowAggregationUMP2::doUDAF(const Row& rowIn, int64_t colIn, int64_t colOut,
// Call the UDAF subEvaluate method // Call the UDAF subEvaluate method
mcsv1sdk::mcsv1_UDAF::ReturnCode rc; mcsv1sdk::mcsv1_UDAF::ReturnCode rc;
boost::shared_ptr<mcsv1sdk::UserData> userData = rowIn.getUserData(colIn+1);
if (!userData)
{
rowUDAF->bInterrupted = true;
throw logic_error("UDAF subevaluate : No userData");
}
rc = rgContext.getFunction()->subEvaluate(&rgContext, userData.get()); rc = rgContext.getFunction()->subEvaluate(&rgContext, userData.get());
rgContext.setUserData(NULL); rgContext.setUserData(NULL);
if (rc == mcsv1sdk::mcsv1_UDAF::ERROR) if (rc == mcsv1sdk::mcsv1_UDAF::ERROR)

View File

@ -62,7 +62,7 @@ mcsv1_UDAF::ReturnCode ssq::init(mcsv1Context* context,
context->setColWidth(8); context->setColWidth(8);
context->setScale(context->getScale()*2); context->setScale(context->getScale()*2);
context->setPrecision(19); context->setPrecision(19);
context->setRunFlag(mcsv1sdk::UDAF_IGNORE_NULLS); // context->setRunFlag(mcsv1sdk::UDAF_IGNORE_NULLS);
return mcsv1_UDAF::SUCCESS; return mcsv1_UDAF::SUCCESS;
} }
@ -85,9 +85,9 @@ mcsv1_UDAF::ReturnCode ssq::nextValue(mcsv1Context* context,
struct ssq_data* data = (struct ssq_data*)context->getUserData()->data; struct ssq_data* data = (struct ssq_data*)context->getUserData()->data;
DATATYPE val = 0.0; DATATYPE val = 0.0;
if (valIn.empty()) if (context->isParamNull(0) || valIn.empty())
{ {
return mcsv1_UDAF::SUCCESS; // Ought not happen when UDAF_IGNORE_NULLS is on. return mcsv1_UDAF::SUCCESS;
} }
if (valIn.compatible(charTypeId)) if (valIn.compatible(charTypeId))
@ -155,6 +155,12 @@ mcsv1_UDAF::ReturnCode ssq::nextValue(mcsv1Context* context,
mcsv1_UDAF::ReturnCode ssq::subEvaluate(mcsv1Context* context, const UserData* userDataIn) mcsv1_UDAF::ReturnCode ssq::subEvaluate(mcsv1Context* context, const UserData* userDataIn)
{ {
// If we turn off UDAF_IGNORE_NULLS in init(), then NULLS may be sent here in cases of Joins.
// When a NULL value is sent here, userDataIn will be NULL, so check for NULLS.
if (context->isParamNull(0))
{
return mcsv1_UDAF::SUCCESS;
}
struct ssq_data* outData = (struct ssq_data*)context->getUserData()->data; struct ssq_data* outData = (struct ssq_data*)context->getUserData()->data;
struct ssq_data* inData = (struct ssq_data*)userDataIn->data; struct ssq_data* inData = (struct ssq_data*)userDataIn->data;
outData->sumsq += inData->sumsq; outData->sumsq += inData->sumsq;