You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-12-20 01:42:27 +03:00
MCOL-523 Add UDAF and UDAnF SDK
This commit is contained in:
744
utils/rowgroup/rowaggregation.cpp
Normal file → Executable file
744
utils/rowgroup/rowaggregation.cpp
Normal file → Executable file
@@ -28,7 +28,7 @@
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <limits>
|
||||
|
||||
#include <typeinfo>
|
||||
#include "joblisttypes.h"
|
||||
#include "resourcemanager.h"
|
||||
#include "groupconcat.h"
|
||||
@@ -459,7 +459,6 @@ inline void RowAggregation::updateFloatSum(float val1, float val2, int64_t col)
|
||||
fRow.setFloatField(val1 + val2, col);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Verify if the column value is NULL
|
||||
// row(in) - Row to be included in aggregation.
|
||||
@@ -721,6 +720,41 @@ void RowAggregation::setJoinRowGroups(vector<RowGroup> *pSmallSideRG, RowGroup *
|
||||
(*fSmallSideRGs)[i].initRow(&rowSmalls[i]);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// For UDAF, we need to sometimes start a new context.
|
||||
//
|
||||
// This will be called any number of times by each of the batchprimitiveprocessor
|
||||
// threads on the PM and by multple threads on the UM. It must remain
|
||||
// thread safe.
|
||||
//------------------------------------------------------------------------------
|
||||
void RowAggregation::resetUDAF(uint64_t funcColID)
|
||||
{
|
||||
// Get the UDAF class pointer and store in the row definition object.
|
||||
RowUDAFFunctionCol* rowUDAF = dynamic_cast<RowUDAFFunctionCol*>(fFunctionCols[funcColID].get());
|
||||
|
||||
// resetUDAF needs to be re-entrant. Since we're modifying the context object
|
||||
// by creating a new userData, we need a local copy. The copy constructor
|
||||
// doesn't copy userData.
|
||||
mcsv1sdk::mcsv1Context rgContext(rowUDAF->fUDAFContext);
|
||||
|
||||
// Call the user reset for the group userData. Since, at this point,
|
||||
// context's userData will be NULL, reset will generate a new one.
|
||||
mcsv1sdk::mcsv1_UDAF::ReturnCode rc;
|
||||
rc = rgContext.getFunction()->reset(&rgContext);
|
||||
if (rc == mcsv1sdk::mcsv1_UDAF::ERROR)
|
||||
{
|
||||
rowUDAF->bInterrupted = true;
|
||||
throw logging::QueryDataExcept(rgContext.getErrorMessage(), logging::aggregateFuncErr);
|
||||
}
|
||||
|
||||
fRow.setUserDataStore(fRowGroupOut->getRGData()->getUserDataStore());
|
||||
fRow.setUserData(rgContext,
|
||||
rgContext.getUserDataSP(),
|
||||
rgContext.getUserDataSize(),
|
||||
rowUDAF->fAuxColumnIndex);
|
||||
|
||||
rgContext.setUserData(NULL); // Prevents calling deleteUserData on the context.
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Initilalize the data members to meaningful values, setup the hashmap.
|
||||
@@ -780,7 +814,7 @@ void RowAggregation::initialize()
|
||||
//------------------------------------------------------------------------------
|
||||
// Reset the working data to aggregate next logical block
|
||||
//------------------------------------------------------------------------------
|
||||
void RowAggregation::reset()
|
||||
void RowAggregation::aggReset()
|
||||
{
|
||||
fTotalRowCount = 0;
|
||||
fMaxTotalRowCount = AGG_ROWGROUP_SIZE;
|
||||
@@ -798,15 +832,23 @@ void RowAggregation::reset()
|
||||
delete fAggMapPtr;
|
||||
fAggMapPtr = new RowAggMap_t(10, *fHasher, *fEq, *fAlloc);
|
||||
}
|
||||
|
||||
fResultDataVec.clear();
|
||||
fResultDataVec.push_back(fRowGroupOut->getRGData());
|
||||
|
||||
// For UDAF, reset the data
|
||||
for (uint64_t i = 0; i < fFunctionCols.size(); i++)
|
||||
{
|
||||
if (fFunctionCols[i]->fAggFunction == ROWAGG_UDAF)
|
||||
{
|
||||
resetUDAF(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RowAggregationUM::reset()
|
||||
void RowAggregationUM::aggReset()
|
||||
{
|
||||
RowAggregation::reset();
|
||||
RowAggregation::aggReset();
|
||||
|
||||
if (fKeyOnHeap)
|
||||
{
|
||||
@@ -843,6 +885,15 @@ void RowAggregationUM::aggregateRowWithRemap(Row& row)
|
||||
attachGroupConcatAg();
|
||||
inserted.first->second = RowPosition(fResultDataVec.size()-1, fRowGroupOut->getRowCount()-1);
|
||||
|
||||
// If there's UDAF involved, reset the user data.
|
||||
for (uint64_t i = 0; i < fFunctionCols.size(); i++)
|
||||
{
|
||||
if (fFunctionCols[i]->fAggFunction == ROWAGG_UDAF)
|
||||
{
|
||||
resetUDAF(i);
|
||||
}
|
||||
}
|
||||
|
||||
// replace the key value with an equivalent copy, yes this is OK
|
||||
const_cast<RowPosition &>((inserted.first->first)) = pos;
|
||||
}
|
||||
@@ -893,6 +944,16 @@ void RowAggregation::aggregateRow(Row& row)
|
||||
// replace the key value with an equivalent copy, yes this is OK
|
||||
const_cast<RowPosition &>(*(inserted.first)) =
|
||||
RowPosition(fResultDataVec.size() - 1, fRowGroupOut->getRowCount() - 1);
|
||||
|
||||
// If there's UDAF involved, reset the user data.
|
||||
for (uint64_t i = 0; i < fFunctionCols.size(); i++)
|
||||
{
|
||||
if (fFunctionCols[i]->fAggFunction == ROWAGG_UDAF)
|
||||
{
|
||||
resetUDAF(i);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
//fRow.setData(*(inserted.first));
|
||||
@@ -1065,6 +1126,8 @@ void RowAggregation::makeAggFieldsNull(Row& row)
|
||||
case execplan::CalpontSystemCatalog::CHAR:
|
||||
case execplan::CalpontSystemCatalog::VARCHAR:
|
||||
case execplan::CalpontSystemCatalog::TEXT:
|
||||
case execplan::CalpontSystemCatalog::VARBINARY:
|
||||
case execplan::CalpontSystemCatalog::BLOB:
|
||||
{
|
||||
int colWidth = fRowGroupOut->getColumnWidth(colOut);
|
||||
if (colWidth <= 8)
|
||||
@@ -1386,7 +1449,7 @@ void RowAggregation::serialize(messageqcpp::ByteStream& bs) const
|
||||
bs << functionCount;
|
||||
|
||||
for (uint64_t i = 0; i < functionCount; i++)
|
||||
bs << *(fFunctionCols[i].get());
|
||||
fFunctionCols[i]->serialize(bs);
|
||||
}
|
||||
|
||||
|
||||
@@ -1415,9 +1478,18 @@ void RowAggregation::deserialize(messageqcpp::ByteStream& bs)
|
||||
|
||||
for (uint64_t i = 0; i < functionCount; i++)
|
||||
{
|
||||
SP_ROWAGG_FUNC_t funct(
|
||||
new RowAggFunctionCol(ROWAGG_FUNCT_UNDEFINE, ROWAGG_FUNCT_UNDEFINE, 0, 0));
|
||||
bs >> *(funct.get());
|
||||
uint8_t funcType;
|
||||
bs.peek(funcType);
|
||||
SP_ROWAGG_FUNC_t funct;
|
||||
if (funcType == ROWAGG_UDAF)
|
||||
{
|
||||
funct.reset(new RowUDAFFunctionCol(0, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
funct.reset(new RowAggFunctionCol(ROWAGG_FUNCT_UNDEFINE, ROWAGG_FUNCT_UNDEFINE, 0, 0));
|
||||
}
|
||||
funct->deserialize(bs);
|
||||
fFunctionCols.push_back(funct);
|
||||
}
|
||||
}
|
||||
@@ -1477,6 +1549,20 @@ void RowAggregation::updateEntry(const Row& rowIn)
|
||||
case ROWAGG_GROUP_CONCAT:
|
||||
break;
|
||||
|
||||
case ROWAGG_UDAF:
|
||||
{
|
||||
RowUDAFFunctionCol* rowUDAF = dynamic_cast<RowUDAFFunctionCol*>(fFunctionCols[i].get());
|
||||
if (rowUDAF)
|
||||
{
|
||||
doUDAF(rowIn, colIn, colOut, colOut + 1, rowUDAF);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw logic_error("(3)A UDAF function is called but there's no RowUDAFFunctionCol");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
@@ -1729,6 +1815,113 @@ void RowAggregation::doStatistics(const Row& rowIn, int64_t colIn, int64_t colOu
|
||||
fRow.setLongDoubleField(fRow.getLongDoubleField(colAux+1) + valIn*valIn, colAux+1);
|
||||
}
|
||||
|
||||
void RowAggregation::doUDAF(const Row& rowIn, int64_t colIn, int64_t colOut, int64_t colAux,
|
||||
RowUDAFFunctionCol* rowUDAF)
|
||||
{
|
||||
std::vector<mcsv1sdk::ColumnDatum> valsIn;
|
||||
execplan::CalpontSystemCatalog::ColDataType colDataType = fRowGroupIn.getColTypes()[colIn];
|
||||
std::vector<uint32_t> dataFlags;
|
||||
|
||||
// Get the context for this rowGroup. Make a copy so we're thread safe.
|
||||
mcsv1sdk::mcsv1Context rgContext(rowUDAF->fUDAFContext);
|
||||
|
||||
// Turn on NULL flags
|
||||
std::vector<uint32_t> flags;
|
||||
uint32_t flag = 0;
|
||||
if (isNull(&fRowGroupIn, rowIn, colIn) == true)
|
||||
{
|
||||
if (rgContext.getRunFlag(mcsv1sdk::UDAF_IGNORE_NULLS))
|
||||
{
|
||||
return;
|
||||
}
|
||||
flag |= mcsv1sdk::PARAM_IS_NULL;
|
||||
}
|
||||
flags.push_back(flag);
|
||||
rgContext.setDataFlags(&flags);
|
||||
|
||||
mcsv1sdk::ColumnDatum datum;
|
||||
|
||||
switch (colDataType)
|
||||
{
|
||||
case execplan::CalpontSystemCatalog::TINYINT:
|
||||
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;
|
||||
datum.columnData = rowIn.getIntField(colIn);
|
||||
datum.scale = fRowGroupIn.getScale()[colIn];
|
||||
datum.precision = fRowGroupIn.getPrecision()[colIn];
|
||||
break;
|
||||
}
|
||||
case execplan::CalpontSystemCatalog::UTINYINT:
|
||||
case execplan::CalpontSystemCatalog::USMALLINT:
|
||||
case execplan::CalpontSystemCatalog::UMEDINT:
|
||||
case execplan::CalpontSystemCatalog::UINT:
|
||||
case execplan::CalpontSystemCatalog::UBIGINT:
|
||||
{
|
||||
datum.dataType = execplan::CalpontSystemCatalog::UBIGINT;
|
||||
datum.columnData = rowIn.getUintField(colIn);
|
||||
break;
|
||||
}
|
||||
case execplan::CalpontSystemCatalog::DOUBLE:
|
||||
case execplan::CalpontSystemCatalog::UDOUBLE:
|
||||
{
|
||||
datum.dataType = execplan::CalpontSystemCatalog::DOUBLE;
|
||||
datum.columnData = rowIn.getDoubleField(colIn);
|
||||
break;
|
||||
}
|
||||
case execplan::CalpontSystemCatalog::FLOAT:
|
||||
case execplan::CalpontSystemCatalog::UFLOAT:
|
||||
{
|
||||
datum.dataType = execplan::CalpontSystemCatalog::FLOAT;
|
||||
datum.columnData = rowIn.getFloatField(colIn);
|
||||
break;
|
||||
}
|
||||
case execplan::CalpontSystemCatalog::DATE:
|
||||
case execplan::CalpontSystemCatalog::DATETIME:
|
||||
{
|
||||
datum.dataType = execplan::CalpontSystemCatalog::UBIGINT;
|
||||
datum.columnData = rowIn.getUintField(colIn);
|
||||
break;
|
||||
}
|
||||
case execplan::CalpontSystemCatalog::CHAR:
|
||||
case execplan::CalpontSystemCatalog::VARCHAR:
|
||||
case execplan::CalpontSystemCatalog::TEXT:
|
||||
case execplan::CalpontSystemCatalog::VARBINARY:
|
||||
case execplan::CalpontSystemCatalog::CLOB:
|
||||
case execplan::CalpontSystemCatalog::BLOB:
|
||||
{
|
||||
datum.dataType = colDataType;
|
||||
datum.columnData = rowIn.getStringField(colIn);
|
||||
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);
|
||||
|
||||
// The intermediate values are stored in userData referenced by colAux.
|
||||
rgContext.setUserData(fRow.getUserData(colAux));
|
||||
|
||||
mcsv1sdk::mcsv1_UDAF::ReturnCode rc;
|
||||
rc = rgContext.getFunction()->nextValue(&rgContext, valsIn);
|
||||
rgContext.setUserData(NULL);
|
||||
if (rc == mcsv1sdk::mcsv1_UDAF::ERROR)
|
||||
{
|
||||
rowUDAF->bInterrupted = true;
|
||||
throw logging::QueryDataExcept(rgContext.getErrorMessage(), logging::aggregateFuncErr);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Allocate a new data array for the output RowGroup
|
||||
@@ -1781,7 +1974,6 @@ void RowAggregation::loadEmptySet(messageqcpp::ByteStream& bs)
|
||||
fEmptyRowGroup.serializeRGData(bs);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Row Aggregation constructor used on UM
|
||||
// For one-phase case, from projected RG to final aggregated RG
|
||||
@@ -1790,10 +1982,11 @@ RowAggregationUM::RowAggregationUM(const vector<SP_ROWAGG_GRPBY_t>& rowAggGroupB
|
||||
const vector<SP_ROWAGG_FUNC_t>& rowAggFunctionCols,
|
||||
joblist::ResourceManager *r, boost::shared_ptr<int64_t> sessionLimit) :
|
||||
RowAggregation(rowAggGroupByCols, rowAggFunctionCols), fHasAvg(false), fKeyOnHeap(false),
|
||||
fHasStatsFunc(false), fTotalMemUsage(0), fRm(r), fSessionMemLimit(sessionLimit),
|
||||
fLastMemUsage(0), fNextRGIndex(0)
|
||||
fHasStatsFunc(false), fHasUDAF(false),fTotalMemUsage(0), fRm(r),
|
||||
fSessionMemLimit(sessionLimit), fLastMemUsage(0), fNextRGIndex(0)
|
||||
{
|
||||
// Check if there are any avg functions.
|
||||
// Check if there are any avg, stats or UDAF functions.
|
||||
// These flags are used in finalize.
|
||||
for (uint64_t i = 0; i < fFunctionCols.size(); i++)
|
||||
{
|
||||
if (fFunctionCols[i]->fAggFunction == ROWAGG_AVG ||
|
||||
@@ -1801,6 +1994,8 @@ RowAggregationUM::RowAggregationUM(const vector<SP_ROWAGG_GRPBY_t>& rowAggGroupB
|
||||
fHasAvg = true;
|
||||
else if (fFunctionCols[i]->fAggFunction == ROWAGG_STATS)
|
||||
fHasStatsFunc = true;
|
||||
else if (fFunctionCols[i]->fAggFunction == ROWAGG_UDAF)
|
||||
fHasUDAF = true;
|
||||
}
|
||||
|
||||
// Check if all groupby column selected
|
||||
@@ -1904,6 +2099,11 @@ void RowAggregationUM::finalize()
|
||||
calculateStatisticsFunctions();
|
||||
}
|
||||
|
||||
if (fHasUDAF)
|
||||
{
|
||||
calculateUDAFColumns();
|
||||
}
|
||||
|
||||
if (fGroupConcat.size() > 0)
|
||||
setGroupConcatString();
|
||||
|
||||
@@ -1950,6 +2150,7 @@ void RowAggregationUM::updateEntry(const Row& rowIn)
|
||||
{
|
||||
int64_t colIn = fFunctionCols[i]->fInputColumnIndex;
|
||||
int64_t colOut = fFunctionCols[i]->fOutputColumnIndex;
|
||||
int64_t colAux = fFunctionCols[i]->fAuxColumnIndex;
|
||||
|
||||
switch (fFunctionCols[i]->fAggFunction)
|
||||
{
|
||||
@@ -1971,14 +2172,12 @@ void RowAggregationUM::updateEntry(const Row& rowIn)
|
||||
// The sum and count on UM may not be put next to each other:
|
||||
// use colOut to store the sum;
|
||||
// use colAux to store the count.
|
||||
int64_t colAux = fFunctionCols[i]->fAuxColumnIndex;
|
||||
doAvg(rowIn, colIn, colOut, colAux);
|
||||
break;
|
||||
}
|
||||
|
||||
case ROWAGG_STATS:
|
||||
{
|
||||
int64_t colAux = fFunctionCols[i]->fAuxColumnIndex;
|
||||
doStatistics(rowIn, colIn, colOut, colAux);
|
||||
break;
|
||||
}
|
||||
@@ -2004,6 +2203,20 @@ void RowAggregationUM::updateEntry(const Row& rowIn)
|
||||
case ROWAGG_CONSTANT:
|
||||
break;
|
||||
|
||||
case ROWAGG_UDAF:
|
||||
{
|
||||
RowUDAFFunctionCol* rowUDAF = dynamic_cast<RowUDAFFunctionCol*>(fFunctionCols[i].get());
|
||||
if (rowUDAF)
|
||||
{
|
||||
doUDAF(rowIn, colIn, colOut, colAux, rowUDAF);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw logic_error("(5)A UDAF function is called but there's no RowUDAFFunctionCol");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
// need a exception to show the value
|
||||
@@ -2143,6 +2356,251 @@ void RowAggregationUM::calculateAvgColumns()
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the value from valOut into column colOut, performing any conversions.
|
||||
void RowAggregationUM::SetUDAFValue(static_any::any& valOut, int64_t colOut)
|
||||
{
|
||||
static const static_any::any& charTypeId = (char)1;
|
||||
static const static_any::any& scharTypeId = (signed char)1;
|
||||
static const static_any::any& shortTypeId = (short)1;
|
||||
static const static_any::any& intTypeId = (int)1;
|
||||
static const static_any::any& longTypeId = (long)1;
|
||||
static const static_any::any& llTypeId = (long long)1;
|
||||
static const static_any::any& ucharTypeId = (unsigned char)1;
|
||||
static const static_any::any& ushortTypeId = (unsigned short)1;
|
||||
static const static_any::any& uintTypeId = (unsigned int)1;
|
||||
static const static_any::any& ulongTypeId = (unsigned long)1;
|
||||
static const static_any::any& ullTypeId = (unsigned long long)1;
|
||||
static const static_any::any& floatTypeId = (float)1;
|
||||
static const static_any::any& doubleTypeId = (double)1;
|
||||
static const std::string typeStr("");
|
||||
static const static_any::any& strTypeId = typeStr;
|
||||
|
||||
execplan::CalpontSystemCatalog::ColDataType colDataType = fRowGroupOut->getColTypes()[colOut];
|
||||
if (valOut.empty())
|
||||
{
|
||||
// Fields are initialized to NULL, which is what we want for empty;
|
||||
return;
|
||||
}
|
||||
|
||||
// This may seem a bit convoluted. Users shouldn't return a type
|
||||
// that they didn't set in mcsv1_UDAF::init(), but this
|
||||
// handles whatever return type is given and casts
|
||||
// it to whatever they said to return.
|
||||
int64_t intOut = 0;
|
||||
uint64_t uintOut = 0;
|
||||
float floatOut = 0.0;
|
||||
double doubleOut = 0.0;
|
||||
ostringstream oss;
|
||||
std::string strOut;
|
||||
|
||||
if (valOut.compatible(charTypeId))
|
||||
{
|
||||
uintOut = intOut = valOut.cast<char>();
|
||||
floatOut = intOut;
|
||||
oss << intOut;
|
||||
}
|
||||
else if (valOut.compatible(scharTypeId))
|
||||
{
|
||||
uintOut = intOut = valOut.cast<signed char>();
|
||||
floatOut = intOut;
|
||||
oss << intOut;
|
||||
}
|
||||
else if (valOut.compatible(shortTypeId))
|
||||
{
|
||||
uintOut = intOut = valOut.cast<short>();
|
||||
floatOut = intOut;
|
||||
oss << intOut;
|
||||
}
|
||||
else if (valOut.compatible(intTypeId))
|
||||
{
|
||||
uintOut = intOut = valOut.cast<int>();
|
||||
floatOut = intOut;
|
||||
oss << intOut;
|
||||
}
|
||||
else if (valOut.compatible(longTypeId))
|
||||
{
|
||||
uintOut = intOut = valOut.cast<long>();
|
||||
floatOut = intOut;
|
||||
oss << intOut;
|
||||
}
|
||||
else if (valOut.compatible(llTypeId))
|
||||
{
|
||||
uintOut = intOut = valOut.cast<long long>();
|
||||
floatOut = intOut;
|
||||
oss << intOut;
|
||||
}
|
||||
else if (valOut.compatible(ucharTypeId))
|
||||
{
|
||||
intOut = uintOut = valOut.cast<unsigned char>();
|
||||
floatOut = uintOut;
|
||||
oss << uintOut;
|
||||
}
|
||||
else if (valOut.compatible(ushortTypeId))
|
||||
{
|
||||
intOut = uintOut = valOut.cast<unsigned short>();
|
||||
floatOut = uintOut;
|
||||
oss << uintOut;
|
||||
}
|
||||
else if (valOut.compatible(uintTypeId))
|
||||
{
|
||||
intOut = uintOut = valOut.cast<unsigned int>();
|
||||
floatOut = uintOut;
|
||||
oss << uintOut;
|
||||
}
|
||||
else if (valOut.compatible(ulongTypeId))
|
||||
{
|
||||
intOut = uintOut = valOut.cast<unsigned long>();
|
||||
floatOut = uintOut;
|
||||
oss << uintOut;
|
||||
}
|
||||
else if (valOut.compatible(ullTypeId))
|
||||
{
|
||||
intOut = uintOut = valOut.cast<unsigned long long>();
|
||||
floatOut = uintOut;
|
||||
oss << uintOut;
|
||||
}
|
||||
else if (valOut.compatible(floatTypeId))
|
||||
{
|
||||
floatOut = valOut.cast<float>();
|
||||
doubleOut = floatOut;
|
||||
intOut = uintOut = floatOut;
|
||||
oss << floatOut;
|
||||
}
|
||||
else if (valOut.compatible(doubleTypeId))
|
||||
{
|
||||
doubleOut = valOut.cast<double>();
|
||||
floatOut = (float)doubleOut;
|
||||
uintOut = (uint64_t)doubleOut;
|
||||
intOut = (int64_t)doubleOut;
|
||||
oss << doubleOut;
|
||||
}
|
||||
|
||||
if (valOut.compatible(strTypeId))
|
||||
{
|
||||
std::string strOut = valOut.cast<std::string>();
|
||||
// Convert the string to numeric type, just in case.
|
||||
intOut = atol(strOut.c_str());
|
||||
uintOut = strtoul(strOut.c_str(), NULL, 10);
|
||||
doubleOut = strtod(strOut.c_str(), NULL);
|
||||
floatOut = (float)doubleOut;
|
||||
}
|
||||
else
|
||||
{
|
||||
strOut = oss.str();
|
||||
}
|
||||
|
||||
switch (colDataType)
|
||||
{
|
||||
case execplan::CalpontSystemCatalog::BIT:
|
||||
case execplan::CalpontSystemCatalog::TINYINT:
|
||||
fRow.setIntField<1>(intOut, colOut);
|
||||
break;
|
||||
case execplan::CalpontSystemCatalog::SMALLINT:
|
||||
case execplan::CalpontSystemCatalog::MEDINT:
|
||||
fRow.setIntField<2>(intOut, colOut);
|
||||
break;
|
||||
case execplan::CalpontSystemCatalog::INT:
|
||||
fRow.setIntField<4>(intOut, colOut);
|
||||
break;
|
||||
case execplan::CalpontSystemCatalog::BIGINT:
|
||||
case execplan::CalpontSystemCatalog::DECIMAL:
|
||||
case execplan::CalpontSystemCatalog::UDECIMAL:
|
||||
fRow.setIntField<8>(intOut, colOut);
|
||||
break;
|
||||
case execplan::CalpontSystemCatalog::UTINYINT:
|
||||
fRow.setUintField<1>(uintOut, colOut);
|
||||
break;
|
||||
case execplan::CalpontSystemCatalog::USMALLINT:
|
||||
case execplan::CalpontSystemCatalog::UMEDINT:
|
||||
fRow.setUintField<2>(uintOut, colOut);
|
||||
break;
|
||||
case execplan::CalpontSystemCatalog::UINT:
|
||||
fRow.setUintField<4>(uintOut, colOut);
|
||||
break;
|
||||
case execplan::CalpontSystemCatalog::UBIGINT:
|
||||
fRow.setUintField<8>(uintOut, colOut);
|
||||
break;
|
||||
case execplan::CalpontSystemCatalog::DATE:
|
||||
case execplan::CalpontSystemCatalog::DATETIME:
|
||||
|
||||
fRow.setUintField<8>(uintOut, colOut);
|
||||
break;
|
||||
case execplan::CalpontSystemCatalog::FLOAT:
|
||||
case execplan::CalpontSystemCatalog::UFLOAT:
|
||||
fRow.setFloatField(floatOut, colOut);
|
||||
break;
|
||||
case execplan::CalpontSystemCatalog::DOUBLE:
|
||||
case execplan::CalpontSystemCatalog::UDOUBLE:
|
||||
fRow.setDoubleField(doubleOut, colOut);
|
||||
break;
|
||||
case execplan::CalpontSystemCatalog::CHAR:
|
||||
case execplan::CalpontSystemCatalog::VARCHAR:
|
||||
case execplan::CalpontSystemCatalog::TEXT:
|
||||
fRow.setStringField(strOut, colOut);
|
||||
break;
|
||||
case execplan::CalpontSystemCatalog::VARBINARY:
|
||||
case execplan::CalpontSystemCatalog::CLOB:
|
||||
case execplan::CalpontSystemCatalog::BLOB:
|
||||
fRow.setVarBinaryField(strOut, colOut);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << "RowAggregation: No logic for data type: " << colDataType;
|
||||
throw logging::QueryDataExcept(errmsg.str(), logging::aggregateFuncErr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// For each rowgroup, calculate the final value.
|
||||
//------------------------------------------------------------------------------
|
||||
void RowAggregationUM::calculateUDAFColumns()
|
||||
{
|
||||
RowUDAFFunctionCol* rowUDAF = NULL;
|
||||
static_any::any valOut;
|
||||
|
||||
|
||||
for (uint64_t i = 0; i < fFunctionCols.size(); i++)
|
||||
{
|
||||
if (fFunctionCols[i]->fAggFunction != ROWAGG_UDAF)
|
||||
continue;
|
||||
|
||||
rowUDAF = dynamic_cast<RowUDAFFunctionCol*>(fFunctionCols[i].get());
|
||||
mcsv1sdk::mcsv1Context rgContext(rowUDAF->fUDAFContext);
|
||||
|
||||
int64_t colOut = rowUDAF->fOutputColumnIndex;
|
||||
int64_t colAux = rowUDAF->fAuxColumnIndex;
|
||||
|
||||
// At this point, each row is an aggregated GROUP BY.
|
||||
for (uint64_t j = 0; j < fRowGroupOut->getRowCount(); j++)
|
||||
{
|
||||
// Get the user data from the row and evaluate.
|
||||
fRowGroupOut->getRow(j, &fRow);
|
||||
|
||||
// Turn the NULL flag off. We can't know NULL at this point
|
||||
rgContext.setDataFlags(NULL);
|
||||
|
||||
// The intermediate values are stored in colAux.
|
||||
rgContext.setUserData(fRow.getUserData(colAux));
|
||||
// Call the UDAF evaluate function
|
||||
mcsv1sdk::mcsv1_UDAF::ReturnCode rc;
|
||||
rc = rgContext.getFunction()->evaluate(&rgContext, valOut);
|
||||
rgContext.setUserData(NULL);
|
||||
if (rc == mcsv1sdk::mcsv1_UDAF::ERROR)
|
||||
{
|
||||
rowUDAF->bInterrupted = true;
|
||||
throw logging::QueryDataExcept(rgContext.getErrorMessage(), logging::aggregateFuncErr);
|
||||
}
|
||||
|
||||
// Set the returned value into the output row
|
||||
SetUDAFValue(valOut, colOut);
|
||||
}
|
||||
rgContext.setUserData(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// After all PM rowgroups received, calculate the statistics.
|
||||
@@ -2222,7 +2680,6 @@ void RowAggregationUM::calculateStatisticsFunctions()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Fix the duplicate function columns -- same function same column id repeated
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -2248,7 +2705,6 @@ void RowAggregationUM::fixDuplicates(RowAggFunctionType funct)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Evaluate the functions and expressions
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -2262,7 +2718,6 @@ void RowAggregationUM::evaluateExpression()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Calculate the aggregate(constant) columns
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -2395,6 +2850,58 @@ void RowAggregationUM::doNullConstantAggregate(const ConstantAggData& aggData, u
|
||||
}
|
||||
break;
|
||||
|
||||
case ROWAGG_UDAF:
|
||||
{
|
||||
int64_t rowCnt = 0;
|
||||
// For a NULL constant, call nextValue with NULL and then evaluate.
|
||||
bool bInterrupted = false;
|
||||
mcsv1sdk::mcsv1Context context;
|
||||
context.setRowCnt(rowCnt);
|
||||
context.setInterrupted(bInterrupted);
|
||||
context.createUserData();
|
||||
mcsv1sdk::mcsv1_UDAF::ReturnCode rc;
|
||||
std::vector<mcsv1sdk::ColumnDatum> valsIn;
|
||||
|
||||
// Call a reset, then nextValue, then execute. This will evaluate
|
||||
// the UDAF for the constant.
|
||||
rc = context.getFunction()->reset(&context);
|
||||
if (rc == mcsv1sdk::mcsv1_UDAF::ERROR)
|
||||
{
|
||||
context.setInterrupted(true);
|
||||
throw logging::QueryDataExcept(context.getErrorMessage(), logging::aggregateFuncErr);
|
||||
}
|
||||
|
||||
// Turn the NULL and CONSTANT flags on.
|
||||
std::vector<uint32_t> flags;
|
||||
uint32_t flag = mcsv1sdk::PARAM_IS_NULL | mcsv1sdk::PARAM_IS_CONSTANT;
|
||||
flags.push_back(flag);
|
||||
context.setDataFlags(&flags);
|
||||
|
||||
// Create a dummy datum
|
||||
mcsv1sdk::ColumnDatum datum;
|
||||
datum.dataType = execplan::CalpontSystemCatalog::BIGINT;
|
||||
datum.columnData = 0;
|
||||
valsIn.push_back(datum);
|
||||
|
||||
rc = context.getFunction()->nextValue(&context, valsIn);
|
||||
if (rc == mcsv1sdk::mcsv1_UDAF::ERROR)
|
||||
{
|
||||
context.setInterrupted(true);
|
||||
throw logging::QueryDataExcept(context.getErrorMessage(), logging::aggregateFuncErr);
|
||||
}
|
||||
static_any::any valOut;
|
||||
rc = context.getFunction()->evaluate(&context, valOut);
|
||||
if (rc == mcsv1sdk::mcsv1_UDAF::ERROR)
|
||||
{
|
||||
context.setInterrupted(true);
|
||||
throw logging::QueryDataExcept(context.getErrorMessage(), logging::aggregateFuncErr);
|
||||
}
|
||||
// Set the returned value into the output row
|
||||
SetUDAFValue(valOut, colOut);
|
||||
context.setDataFlags(NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
fRow.setStringField("", colOut);
|
||||
@@ -2674,6 +3181,133 @@ void RowAggregationUM::doNotNullConstantAggregate(const ConstantAggData& aggData
|
||||
}
|
||||
break;
|
||||
|
||||
case ROWAGG_UDAF:
|
||||
{
|
||||
int64_t rowCnt = 0;
|
||||
bool bInterrupted = false;
|
||||
mcsv1sdk::mcsv1Context context;
|
||||
context.setRowCnt(rowCnt);
|
||||
context.setInterrupted(bInterrupted);
|
||||
// Try the complex data initiation. If not implemented, use the simple,
|
||||
context.createUserData();
|
||||
mcsv1sdk::mcsv1_UDAF::ReturnCode rc;
|
||||
std::vector<mcsv1sdk::ColumnDatum> valsIn;
|
||||
|
||||
// Call a reset, then nextValue, then execute. This will evaluate
|
||||
// the UDAF for the constant.
|
||||
rc = context.getFunction()->reset(&context);
|
||||
if (rc == mcsv1sdk::mcsv1_UDAF::ERROR)
|
||||
{
|
||||
context.setInterrupted(true);
|
||||
throw logging::QueryDataExcept(context.getErrorMessage(), logging::aggregateFuncErr);
|
||||
}
|
||||
|
||||
// Turn the CONSTANT flags on.
|
||||
std::vector<uint32_t> flags;
|
||||
uint32_t flag = mcsv1sdk::PARAM_IS_CONSTANT;
|
||||
flags.push_back(flag);
|
||||
context.setDataFlags(&flags);
|
||||
|
||||
// Create a datum item for sending to UDAF
|
||||
mcsv1sdk::ColumnDatum datum;
|
||||
datum.dataType = (CalpontSystemCatalog::ColDataType)colDataType;
|
||||
|
||||
switch (colDataType)
|
||||
{
|
||||
case execplan::CalpontSystemCatalog::TINYINT:
|
||||
case execplan::CalpontSystemCatalog::SMALLINT:
|
||||
case execplan::CalpontSystemCatalog::MEDINT:
|
||||
case execplan::CalpontSystemCatalog::INT:
|
||||
case execplan::CalpontSystemCatalog::BIGINT:
|
||||
{
|
||||
datum.columnData = strtol(aggData.fConstValue.c_str(), 0, 10);
|
||||
}
|
||||
break;
|
||||
|
||||
case execplan::CalpontSystemCatalog::UTINYINT:
|
||||
case execplan::CalpontSystemCatalog::USMALLINT:
|
||||
case execplan::CalpontSystemCatalog::UMEDINT:
|
||||
case execplan::CalpontSystemCatalog::UINT:
|
||||
case execplan::CalpontSystemCatalog::UBIGINT:
|
||||
{
|
||||
datum.columnData = strtoul(aggData.fConstValue.c_str(), 0, 10);
|
||||
}
|
||||
break;
|
||||
|
||||
case execplan::CalpontSystemCatalog::DECIMAL:
|
||||
case execplan::CalpontSystemCatalog::UDECIMAL:
|
||||
{
|
||||
double dbl = strtod(aggData.fConstValue.c_str(), 0);
|
||||
double scale = pow(10.0, (double) fRowGroupOut->getScale()[i]);
|
||||
datum.columnData = (int64_t)(scale*dbl);
|
||||
datum.scale = scale;
|
||||
datum.precision = fRowGroupOut->getPrecision()[i];
|
||||
}
|
||||
break;
|
||||
|
||||
case execplan::CalpontSystemCatalog::DOUBLE:
|
||||
case execplan::CalpontSystemCatalog::UDOUBLE:
|
||||
{
|
||||
datum.columnData = strtod(aggData.fConstValue.c_str(), 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case execplan::CalpontSystemCatalog::FLOAT:
|
||||
case execplan::CalpontSystemCatalog::UFLOAT:
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
datum.columnData = strtod(aggData.fConstValue.c_str(), 0);
|
||||
#else
|
||||
datum.columnData = strtof(aggData.fConstValue.c_str(), 0);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case execplan::CalpontSystemCatalog::DATE:
|
||||
{
|
||||
datum.columnData = DataConvert::stringToDate(aggData.fConstValue);
|
||||
}
|
||||
break;
|
||||
|
||||
case execplan::CalpontSystemCatalog::DATETIME:
|
||||
{
|
||||
datum.columnData = DataConvert::stringToDatetime(aggData.fConstValue);
|
||||
}
|
||||
break;
|
||||
|
||||
case execplan::CalpontSystemCatalog::CHAR:
|
||||
case execplan::CalpontSystemCatalog::VARCHAR:
|
||||
case execplan::CalpontSystemCatalog::TEXT:
|
||||
case execplan::CalpontSystemCatalog::VARBINARY:
|
||||
case execplan::CalpontSystemCatalog::BLOB:
|
||||
default:
|
||||
{
|
||||
datum.columnData = aggData.fConstValue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
valsIn.push_back(datum);
|
||||
rc = context.getFunction()->nextValue(&context, valsIn);
|
||||
if (rc == mcsv1sdk::mcsv1_UDAF::ERROR)
|
||||
{
|
||||
context.setInterrupted(true);
|
||||
throw logging::QueryDataExcept(context.getErrorMessage(), logging::aggregateFuncErr);
|
||||
}
|
||||
|
||||
static_any::any valOut;
|
||||
rc = context.getFunction()->evaluate(&context, valOut);
|
||||
if (rc == mcsv1sdk::mcsv1_UDAF::ERROR)
|
||||
{
|
||||
context.setInterrupted(true);
|
||||
throw logging::QueryDataExcept(context.getErrorMessage(), logging::aggregateFuncErr);
|
||||
}
|
||||
// Set the returned value into the output row
|
||||
SetUDAFValue(valOut, colOut);
|
||||
context.setDataFlags(NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
fRow.setStringField(aggData.fConstValue, colOut);
|
||||
@@ -2823,6 +3457,7 @@ void RowAggregationUMP2::updateEntry(const Row& rowIn)
|
||||
{
|
||||
int64_t colIn = fFunctionCols[i]->fInputColumnIndex;
|
||||
int64_t colOut = fFunctionCols[i]->fOutputColumnIndex;
|
||||
int64_t colAux = fFunctionCols[i]->fAuxColumnIndex;
|
||||
|
||||
switch (fFunctionCols[i]->fAggFunction)
|
||||
{
|
||||
@@ -2845,14 +3480,12 @@ void RowAggregationUMP2::updateEntry(const Row& rowIn)
|
||||
// The sum and count on UM may not be put next to each other:
|
||||
// use colOut to store the sum;
|
||||
// use colAux to store the count.
|
||||
int64_t colAux = fFunctionCols[i]->fAuxColumnIndex;
|
||||
doAvg(rowIn, colIn, colOut, colAux);
|
||||
break;
|
||||
}
|
||||
|
||||
case ROWAGG_STATS:
|
||||
{
|
||||
int64_t colAux = fFunctionCols[i]->fAuxColumnIndex;
|
||||
doStatistics(rowIn, colIn, colOut, colAux);
|
||||
break;
|
||||
}
|
||||
@@ -2878,6 +3511,20 @@ void RowAggregationUMP2::updateEntry(const Row& rowIn)
|
||||
case ROWAGG_CONSTANT:
|
||||
break;
|
||||
|
||||
case ROWAGG_UDAF:
|
||||
{
|
||||
RowUDAFFunctionCol* rowUDAF = dynamic_cast<RowUDAFFunctionCol*>(fFunctionCols[i].get());
|
||||
if (rowUDAF)
|
||||
{
|
||||
doUDAF(rowIn, colIn, colOut, colAux, rowUDAF);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw logic_error("(6)A UDAF function is called but there's no RowUDAFFunctionCol");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
@@ -3050,6 +3697,43 @@ void RowAggregationUMP2::doBitOp(const Row& rowIn, int64_t colIn, int64_t colOut
|
||||
fRow.setUintField(valIn ^ valOut, colOut);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Subaggregate the UDAF. This calls subaggregate for each partially
|
||||
// aggregated row returned by the PM
|
||||
// rowIn(in) - Row to be included in aggregation.
|
||||
// colIn(in) - column in the input row group
|
||||
// colOut(in) - column in the output row group
|
||||
// colAux(in) - Where the UDAF userdata resides
|
||||
// rowUDAF(in) - pointer to the RowUDAFFunctionCol for this UDAF instance
|
||||
//------------------------------------------------------------------------------
|
||||
void RowAggregationUMP2::doUDAF(const Row& rowIn, int64_t colIn, int64_t colOut, int64_t colAux,
|
||||
RowUDAFFunctionCol* rowUDAF)
|
||||
{
|
||||
static_any::any valOut;
|
||||
mcsv1sdk::mcsv1Context rgContext(rowUDAF->fUDAFContext);
|
||||
|
||||
// Turn on NULL flags
|
||||
std::vector<uint32_t> flags;
|
||||
uint32_t flag = 0;
|
||||
if (isNull(&fRowGroupIn, rowIn, colIn) == true)
|
||||
flag |= mcsv1sdk::PARAM_IS_NULL;
|
||||
flags.push_back(flag);
|
||||
rgContext.setDataFlags(&flags);
|
||||
|
||||
// The intermediate values are stored in colAux.
|
||||
rgContext.setUserData(fRow.getUserData(colAux));
|
||||
|
||||
// Call the UDAF subEvaluate method
|
||||
mcsv1sdk::mcsv1_UDAF::ReturnCode rc;
|
||||
rc = rgContext.getFunction()->subEvaluate(&rgContext, rowIn.getUserData(colIn+1).get());
|
||||
rgContext.setUserData(NULL);
|
||||
if (rc == mcsv1sdk::mcsv1_UDAF::ERROR)
|
||||
{
|
||||
rowUDAF->bInterrupted = true;
|
||||
throw logging::QueryDataExcept(rgContext.getErrorMessage(), logging::aggregateFuncErr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -3163,6 +3847,7 @@ void RowAggregationDistinct::updateEntry(const Row& rowIn)
|
||||
{
|
||||
int64_t colIn = fFunctionCols[i]->fInputColumnIndex;
|
||||
int64_t colOut = fFunctionCols[i]->fOutputColumnIndex;
|
||||
int64_t colAux = fFunctionCols[i]->fAuxColumnIndex;
|
||||
|
||||
switch (fFunctionCols[i]->fAggFunction)
|
||||
{
|
||||
@@ -3192,7 +3877,6 @@ void RowAggregationDistinct::updateEntry(const Row& rowIn)
|
||||
// The sum and count on UM may not be put next to each other:
|
||||
// use colOut to store the sum;
|
||||
// use colAux to store the count.
|
||||
int64_t colAux = fFunctionCols[i]->fAuxColumnIndex;
|
||||
doAvg(rowIn, colIn, colOut, colAux);
|
||||
break;
|
||||
}
|
||||
@@ -3202,14 +3886,12 @@ void RowAggregationDistinct::updateEntry(const Row& rowIn)
|
||||
// The sum and count on UM may not be put next to each other:
|
||||
// use colOut to store the sum;
|
||||
// use colAux to store the count.
|
||||
int64_t colAux = fFunctionCols[i]->fAuxColumnIndex;
|
||||
RowAggregation::doAvg(rowIn, colIn, colOut, colAux);
|
||||
break;
|
||||
}
|
||||
|
||||
case ROWAGG_STATS:
|
||||
{
|
||||
int64_t colAux = fFunctionCols[i]->fAuxColumnIndex;
|
||||
doStatistics(rowIn, colIn, colOut, colAux);
|
||||
break;
|
||||
}
|
||||
@@ -3235,6 +3917,20 @@ void RowAggregationDistinct::updateEntry(const Row& rowIn)
|
||||
case ROWAGG_CONSTANT:
|
||||
break;
|
||||
|
||||
case ROWAGG_UDAF:
|
||||
{
|
||||
RowUDAFFunctionCol* rowUDAF = dynamic_cast<RowUDAFFunctionCol*>(fFunctionCols[i].get());
|
||||
if (rowUDAF)
|
||||
{
|
||||
doUDAF(rowIn, colIn, colOut, colAux, rowUDAF);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw logic_error("(7)A UDAF function is called but there's no RowUDAFFunctionCol");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
|
||||
104
utils/rowgroup/rowaggregation.h
Normal file → Executable file
104
utils/rowgroup/rowaggregation.h
Normal file → Executable file
@@ -49,6 +49,7 @@
|
||||
#include "hasher.h"
|
||||
#include "stlpoolallocator.h"
|
||||
#include "returnedcolumn.h"
|
||||
#include "mcsv1_udaf.h"
|
||||
|
||||
// To do: move code that depends on joblist to a proper subsystem.
|
||||
namespace joblist
|
||||
@@ -64,6 +65,7 @@ struct RowPosition
|
||||
{
|
||||
uint64_t group:48;
|
||||
uint64_t row:16;
|
||||
|
||||
static const uint64_t MSB = 0x800000000000ULL; //48th bit is set
|
||||
inline RowPosition(uint64_t g, uint64_t r) : group(g), row(r) { }
|
||||
inline RowPosition() { }
|
||||
@@ -105,6 +107,9 @@ enum RowAggFunctionType
|
||||
// Constant
|
||||
ROWAGG_CONSTANT,
|
||||
|
||||
// User Defined Aggregate Function
|
||||
ROWAGG_UDAF,
|
||||
|
||||
// internal function type to avoid duplicate the work
|
||||
// handling ROWAGG_COUNT_NO_OP, ROWAGG_DUP_FUNCT and ROWAGG_DUP_AVG is a little different
|
||||
// ROWAGG_COUNT_NO_OP : count done by AVG, no need to copy
|
||||
@@ -169,7 +174,10 @@ struct RowAggFunctionCol
|
||||
int32_t inputColIndex, int32_t outputColIndex, int32_t auxColIndex = -1) :
|
||||
fAggFunction(aggFunction), fStatsFunction(stats), fInputColumnIndex(inputColIndex),
|
||||
fOutputColumnIndex(outputColIndex), fAuxColumnIndex(auxColIndex) {}
|
||||
~RowAggFunctionCol() {}
|
||||
virtual ~RowAggFunctionCol() {}
|
||||
|
||||
virtual void serialize(messageqcpp::ByteStream& bs) const;
|
||||
virtual void deserialize(messageqcpp::ByteStream& bs);
|
||||
|
||||
RowAggFunctionType fAggFunction; // aggregate function
|
||||
// statistics function stores ROWAGG_STATS in fAggFunction and real function in fStatsFunction
|
||||
@@ -178,24 +186,86 @@ struct RowAggFunctionCol
|
||||
uint32_t fInputColumnIndex;
|
||||
uint32_t fOutputColumnIndex;
|
||||
|
||||
// fAuxColumnIndex is used in 3 cases:
|
||||
// fAuxColumnIndex is used in 4 cases:
|
||||
// 1. for AVG - point to the count column, the fInputColumnIndex is for sum
|
||||
// 2. for statistics function - point to sum(x), +1 is sum(x**2)
|
||||
// 3. for duplicate - point to the real aggretate column to be copied from
|
||||
// 3. for UDAF - contain the context user data as binary
|
||||
// 4. for duplicate - point to the real aggretate column to be copied from
|
||||
// Set only on UM, the fAuxColumnIndex is defaulted to fOutputColumnIndex+1 on PM.
|
||||
uint32_t fAuxColumnIndex;
|
||||
};
|
||||
|
||||
inline messageqcpp::ByteStream& operator<<(messageqcpp::ByteStream& b, RowAggFunctionCol& o)
|
||||
{ return (b << (uint8_t)o.fAggFunction << o.fInputColumnIndex << o.fOutputColumnIndex); }
|
||||
inline messageqcpp::ByteStream& operator>>(messageqcpp::ByteStream& b, RowAggFunctionCol& o)
|
||||
{ return (b >> (uint8_t&)o.fAggFunction >> o.fInputColumnIndex >> o.fOutputColumnIndex); }
|
||||
|
||||
struct RowUDAFFunctionCol : public RowAggFunctionCol
|
||||
{
|
||||
RowUDAFFunctionCol(mcsv1sdk::mcsv1Context& context, int32_t inputColIndex,
|
||||
int32_t outputColIndex, int32_t auxColIndex = -1) :
|
||||
RowAggFunctionCol(ROWAGG_UDAF, ROWAGG_FUNCT_UNDEFINE,
|
||||
inputColIndex, outputColIndex, auxColIndex),
|
||||
fUDAFContext(context), bInterrupted(false)
|
||||
{
|
||||
fUDAFContext.setInterrupted(&bInterrupted);
|
||||
}
|
||||
|
||||
RowUDAFFunctionCol(int32_t inputColIndex,
|
||||
int32_t outputColIndex, int32_t auxColIndex = -1) :
|
||||
RowAggFunctionCol(ROWAGG_UDAF, ROWAGG_FUNCT_UNDEFINE,
|
||||
inputColIndex, outputColIndex, auxColIndex),
|
||||
bInterrupted(false)
|
||||
{}
|
||||
RowUDAFFunctionCol(const RowUDAFFunctionCol& rhs) : RowAggFunctionCol(ROWAGG_UDAF, ROWAGG_FUNCT_UNDEFINE,
|
||||
rhs.fInputColumnIndex, rhs.fOutputColumnIndex, rhs.fAuxColumnIndex), fUDAFContext(rhs.fUDAFContext)
|
||||
{}
|
||||
|
||||
virtual ~RowUDAFFunctionCol() {}
|
||||
|
||||
virtual void serialize(messageqcpp::ByteStream& bs) const;
|
||||
virtual void deserialize(messageqcpp::ByteStream& bs);
|
||||
|
||||
mcsv1sdk::mcsv1Context fUDAFContext; // The UDAF context
|
||||
bool bInterrupted; // Shared by all the threads
|
||||
};
|
||||
|
||||
inline void RowAggFunctionCol::serialize(messageqcpp::ByteStream& bs) const
|
||||
{
|
||||
bs << (uint8_t)fAggFunction;
|
||||
bs << fInputColumnIndex;
|
||||
bs << fOutputColumnIndex;
|
||||
}
|
||||
|
||||
inline void RowAggFunctionCol::deserialize(messageqcpp::ByteStream& bs)
|
||||
{
|
||||
bs >> (uint8_t&)fAggFunction;
|
||||
bs >> fInputColumnIndex;
|
||||
bs >> fOutputColumnIndex;
|
||||
}
|
||||
|
||||
inline void RowUDAFFunctionCol::serialize(messageqcpp::ByteStream& bs) const
|
||||
{
|
||||
RowAggFunctionCol::serialize(bs);
|
||||
fUDAFContext.serialize(bs);
|
||||
}
|
||||
|
||||
inline void RowUDAFFunctionCol::deserialize(messageqcpp::ByteStream& bs)
|
||||
{
|
||||
// This deserialize is called when the function gets to PrimProc.
|
||||
// reset is called because we're starting a new sub-evaluate cycle.
|
||||
RowAggFunctionCol::deserialize(bs);
|
||||
fUDAFContext.unserialize(bs);
|
||||
fUDAFContext.setInterrupted(&bInterrupted);
|
||||
mcsv1sdk::mcsv1_UDAF::ReturnCode rc;
|
||||
rc = fUDAFContext.getFunction()->reset(&fUDAFContext);
|
||||
if (rc == mcsv1sdk::mcsv1_UDAF::ERROR)
|
||||
{
|
||||
bInterrupted = true;
|
||||
throw logging::QueryDataExcept(fUDAFContext.getErrorMessage(), logging::aggregateFuncErr);
|
||||
}
|
||||
}
|
||||
|
||||
struct ConstantAggData
|
||||
{
|
||||
std::string fConstValue;
|
||||
std::string fUDAFName; // If a UDAF is called with constant.
|
||||
RowAggFunctionType fOp;
|
||||
bool fIsNull;
|
||||
|
||||
@@ -205,6 +275,10 @@ struct ConstantAggData
|
||||
ConstantAggData(const std::string& v, RowAggFunctionType f, bool n) :
|
||||
fConstValue(v), fOp(f), fIsNull(n)
|
||||
{}
|
||||
|
||||
ConstantAggData(const std::string& v, const std::string u, RowAggFunctionType f, bool n) :
|
||||
fConstValue(v), fUDAFName(u), fOp(f), fIsNull(n)
|
||||
{}
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<RowAggGroupByCol> SP_ROWAGG_GRPBY_t;
|
||||
@@ -377,7 +451,7 @@ class RowAggregation : public messageqcpp::Serializeable
|
||||
|
||||
/** @brief reset RowAggregation outputRowGroup and hashMap
|
||||
*/
|
||||
virtual void reset();
|
||||
virtual void aggReset();
|
||||
|
||||
/** @brief Define content of data to be aggregated and its aggregated output.
|
||||
*
|
||||
@@ -470,12 +544,15 @@ class RowAggregation : public messageqcpp::Serializeable
|
||||
virtual void doAvg(const Row&, int64_t, int64_t, int64_t);
|
||||
virtual void doStatistics(const Row&, int64_t, int64_t, int64_t);
|
||||
virtual void doBitOp(const Row&, int64_t, int64_t, int);
|
||||
virtual void doUDAF(const Row&, int64_t, int64_t, int64_t, RowUDAFFunctionCol* rowUDAF);
|
||||
virtual bool countSpecial(const RowGroup* pRG)
|
||||
{ fRow.setIntField<8>(fRow.getIntField<8>(0) + pRG->getRowCount(), 0); return true; }
|
||||
|
||||
virtual bool newRowGroup();
|
||||
virtual void clearAggMap() { if (fAggMapPtr) fAggMapPtr->clear(); }
|
||||
|
||||
void resetUDAF(uint64_t funcColID);
|
||||
|
||||
inline bool isNull(const RowGroup* pRowGroup, const Row& row, int64_t col);
|
||||
inline void makeAggFieldsNull(Row& row);
|
||||
inline void copyNullRow(Row& row) { copyRow(fNullRow, &row); }
|
||||
@@ -537,7 +614,6 @@ class RowAggregation : public messageqcpp::Serializeable
|
||||
friend class AggComparator;
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** @brief derived Class that aggregates multi-rowgroups on UM
|
||||
* One-phase case: aggregate from projected RG to final aggregated RG.
|
||||
@@ -602,7 +678,7 @@ class RowAggregationUM : public RowAggregation
|
||||
|
||||
void aggregateRow(Row &);
|
||||
//void initialize();
|
||||
virtual void reset();
|
||||
virtual void aggReset();
|
||||
|
||||
void setInputOutput(const RowGroup& pRowGroupIn, RowGroup* pRowGroupOut);
|
||||
|
||||
@@ -628,6 +704,12 @@ class RowAggregationUM : public RowAggregation
|
||||
// calculate the statistics function all rows received. UM only function.
|
||||
void calculateStatisticsFunctions();
|
||||
|
||||
// Sets the value from valOut into column colOut, performing any conversions.
|
||||
void SetUDAFValue(static_any::any& valOut, int64_t colOut);
|
||||
|
||||
// calculate the UDAF function all rows received. UM only function.
|
||||
void calculateUDAFColumns();
|
||||
|
||||
// fix duplicates. UM only function.
|
||||
void fixDuplicates(RowAggFunctionType funct);
|
||||
|
||||
@@ -646,6 +728,7 @@ class RowAggregationUM : public RowAggregation
|
||||
bool fHasAvg;
|
||||
bool fKeyOnHeap;
|
||||
bool fHasStatsFunc;
|
||||
bool fHasUDAF;
|
||||
|
||||
boost::shared_ptr<RowAggregation> fDistinctAggregator;
|
||||
|
||||
@@ -715,6 +798,7 @@ class RowAggregationUMP2 : public RowAggregationUM
|
||||
void doStatistics(const Row&, int64_t, int64_t, int64_t);
|
||||
void doGroupConcat(const Row&, int64_t, int64_t);
|
||||
void doBitOp(const Row&, int64_t, int64_t, int);
|
||||
void doUDAF(const Row&, int64_t, int64_t, int64_t, RowUDAFFunctionCol* rowUDAF);
|
||||
bool countSpecial(const RowGroup* pRG) { return false; }
|
||||
};
|
||||
|
||||
|
||||
175
utils/rowgroup/rowgroup.cpp
Normal file → Executable file
175
utils/rowgroup/rowgroup.cpp
Normal file → Executable file
@@ -38,7 +38,6 @@
|
||||
using namespace std;
|
||||
|
||||
#include <boost/shared_array.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
using namespace boost;
|
||||
|
||||
#include "bytestream.h"
|
||||
@@ -113,7 +112,6 @@ uint32_t StringStore::storeString(const uint8_t *data, uint32_t len)
|
||||
void StringStore::serialize(ByteStream &bs) const
|
||||
{
|
||||
uint32_t i;
|
||||
std::string empty_str;
|
||||
|
||||
bs << (uint32_t) mem.size();
|
||||
bs << (uint8_t) empty;
|
||||
@@ -126,30 +124,25 @@ void StringStore::serialize(ByteStream &bs) const
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t StringStore::deserialize(ByteStream &bs)
|
||||
void StringStore::deserialize(ByteStream &bs)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t count;
|
||||
uint32_t size;
|
||||
std::string buf;
|
||||
uint8_t tmp8;
|
||||
uint32_t ret = 0;
|
||||
|
||||
//mem.clear();
|
||||
bs >> count;
|
||||
mem.reserve(count);
|
||||
bs >> tmp8;
|
||||
empty = (bool) tmp8;
|
||||
ret += 5;
|
||||
for (i = 0; i < count; i++) {
|
||||
//cout << "deserializing " << size << " bytes\n";
|
||||
bs >> buf;
|
||||
shared_ptr<std::string> newString(new std::string(buf));
|
||||
mem.push_back(newString);
|
||||
//bs.advance(size);
|
||||
ret += (size + 4);
|
||||
}
|
||||
return ret;
|
||||
return;
|
||||
}
|
||||
|
||||
void StringStore::clear()
|
||||
@@ -159,6 +152,106 @@ void StringStore::clear()
|
||||
empty = true;
|
||||
}
|
||||
|
||||
UserDataStore::UserDataStore() : fUseUserDataMutex(false)
|
||||
{
|
||||
}
|
||||
|
||||
UserDataStore::~UserDataStore()
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t UserDataStore::storeUserData(mcsv1sdk::mcsv1Context& context,
|
||||
boost::shared_ptr<mcsv1sdk::UserData> data,
|
||||
uint32_t len)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
if (len == 0 || data == NULL)
|
||||
{
|
||||
return numeric_limits<uint32_t>::max();
|
||||
}
|
||||
|
||||
boost::mutex::scoped_lock lk(fMutex, defer_lock);
|
||||
if (fUseUserDataMutex)
|
||||
lk.lock();
|
||||
StoreData storeData;
|
||||
storeData.length = len;
|
||||
storeData.functionName = context.getName();
|
||||
storeData.userData = data;
|
||||
vStoreData.push_back(storeData);
|
||||
|
||||
ret = vStoreData.size();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
boost::shared_ptr<mcsv1sdk::UserData> UserDataStore::getUserData(uint32_t off) const
|
||||
{
|
||||
if (off == std::numeric_limits<uint32_t>::max())
|
||||
return boost::shared_ptr<mcsv1sdk::UserData>();
|
||||
|
||||
if ((vStoreData.size() < off) || off == 0)
|
||||
return boost::shared_ptr<mcsv1sdk::UserData>();
|
||||
|
||||
return vStoreData[off-1].userData;
|
||||
}
|
||||
|
||||
|
||||
void UserDataStore::serialize(ByteStream &bs) const
|
||||
{
|
||||
size_t i;
|
||||
|
||||
bs << (uint32_t) vStoreData.size();
|
||||
for (i = 0; i < vStoreData.size(); ++i)
|
||||
{
|
||||
const StoreData& storeData = vStoreData[i];
|
||||
bs << storeData.length;
|
||||
bs << storeData.functionName;
|
||||
storeData.userData->serialize(bs);
|
||||
}
|
||||
}
|
||||
|
||||
void UserDataStore::deserialize(ByteStream &bs)
|
||||
{
|
||||
size_t i;
|
||||
uint32_t cnt;
|
||||
bs >> cnt;
|
||||
|
||||
// vStoreData.clear();
|
||||
vStoreData.resize(cnt);
|
||||
|
||||
for (i = 0; i < cnt; i++)
|
||||
{
|
||||
bs >> vStoreData[i].length;
|
||||
bs >> vStoreData[i].functionName;
|
||||
|
||||
// We don't have easy access to the context here, so we do our own lookup
|
||||
if (vStoreData[i].functionName.length() == 0)
|
||||
{
|
||||
throw std::logic_error("UserDataStore::deserialize: has empty name");
|
||||
}
|
||||
mcsv1sdk::UDAF_MAP::iterator funcIter = mcsv1sdk::UDAFMap::getMap().find(vStoreData[i].functionName);
|
||||
if (funcIter == mcsv1sdk::UDAFMap::getMap().end())
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << "UserDataStore::deserialize: " << vStoreData[i].functionName << " is undefined";
|
||||
throw std::logic_error(errmsg.str());
|
||||
}
|
||||
|
||||
mcsv1sdk::mcsv1_UDAF::ReturnCode rc;
|
||||
mcsv1sdk::UserData* userData = NULL;
|
||||
rc = funcIter->second->createUserData(userData, vStoreData[i].length);
|
||||
if (rc != mcsv1sdk::mcsv1_UDAF::SUCCESS)
|
||||
{
|
||||
std::ostringstream errmsg;
|
||||
errmsg << "UserDataStore::deserialize: " << vStoreData[i].functionName << " createUserData failed(" << rc << ")";
|
||||
throw std::logic_error(errmsg.str());
|
||||
}
|
||||
userData->unserialize(bs);
|
||||
vStoreData[i].userData = boost::shared_ptr<mcsv1sdk::UserData>(userData);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//uint32_t rgDataCount = 0;
|
||||
|
||||
RGData::RGData()
|
||||
@@ -222,7 +315,7 @@ void RGData::reinit(const RowGroup &rg)
|
||||
reinit(rg, 8192);
|
||||
}
|
||||
|
||||
RGData::RGData(const RGData &r) : rowData(r.rowData), strings(r.strings)
|
||||
RGData::RGData(const RGData &r) : rowData(r.rowData), strings(r.strings), userDataStore(r.userDataStore)
|
||||
{
|
||||
//cout << "rgdata++ = " << __sync_add_and_fetch(&rgDataCount, 1) << endl;
|
||||
}
|
||||
@@ -244,49 +337,47 @@ void RGData::serialize(ByteStream &bs, uint32_t amount) const
|
||||
}
|
||||
else
|
||||
bs << (uint8_t) 0;
|
||||
if (userDataStore)
|
||||
{
|
||||
bs << (uint8_t) 1;
|
||||
userDataStore->serialize(bs);
|
||||
}
|
||||
else
|
||||
bs << (uint8_t) 0;
|
||||
}
|
||||
|
||||
uint32_t RGData::deserialize(ByteStream &bs, bool hasLenField)
|
||||
void RGData::deserialize(ByteStream &bs, bool hasLenField)
|
||||
{
|
||||
uint32_t amount, sig;
|
||||
uint8_t *buf;
|
||||
uint8_t tmp8;
|
||||
uint32_t ret = 0;
|
||||
|
||||
bs.peek(sig);
|
||||
if (sig == RGDATA_SIG) {
|
||||
bs >> sig;
|
||||
bs >> amount;
|
||||
ret += 8;
|
||||
rowData.reset(new uint8_t[amount]);
|
||||
buf = bs.buf();
|
||||
memcpy(rowData.get(), buf, amount);
|
||||
bs.advance(amount);
|
||||
bs >> tmp8;
|
||||
ret += amount + 1;
|
||||
if (tmp8) {
|
||||
strings.reset(new StringStore());
|
||||
ret += strings->deserialize(bs);
|
||||
strings->deserialize(bs);
|
||||
}
|
||||
else
|
||||
strings.reset();
|
||||
}
|
||||
// crude backward compat. Remove after conversions are finished.
|
||||
else {
|
||||
if (hasLenField) {
|
||||
bs >> amount;
|
||||
ret += 4;
|
||||
// UDAF user data
|
||||
bs >> tmp8;
|
||||
if (tmp8) {
|
||||
userDataStore.reset(new UserDataStore());
|
||||
userDataStore->deserialize(bs);
|
||||
}
|
||||
else
|
||||
amount = bs.length();
|
||||
rowData.reset(new uint8_t[amount]);
|
||||
strings.reset();
|
||||
buf = bs.buf();
|
||||
memcpy(rowData.get(), buf, amount);
|
||||
bs.advance(amount);
|
||||
ret += amount;
|
||||
userDataStore.reset();
|
||||
}
|
||||
return ret;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void RGData::clear()
|
||||
@@ -295,14 +386,25 @@ void RGData::clear()
|
||||
strings.reset();
|
||||
}
|
||||
|
||||
Row::Row() : data(NULL), strings(NULL) { }
|
||||
// UserDataStore is only used for UDAF.
|
||||
// Just in time construction because most of the time we don't need one.
|
||||
UserDataStore* RGData::getUserDataStore()
|
||||
{
|
||||
if (!userDataStore)
|
||||
{
|
||||
userDataStore.reset(new UserDataStore);
|
||||
}
|
||||
return userDataStore.get();
|
||||
}
|
||||
|
||||
Row::Row() : data(NULL), strings(NULL), userDataStore(NULL) { }
|
||||
|
||||
Row::Row(const Row &r) : columnCount(r.columnCount), baseRid(r.baseRid),
|
||||
oldOffsets(r.oldOffsets), stOffsets(r.stOffsets),
|
||||
offsets(r.offsets), colWidths(r.colWidths), types(r.types), data(r.data),
|
||||
scale(r.scale), precision(r.precision), strings(r.strings),
|
||||
useStringTable(r.useStringTable), hasLongStringField(r.hasLongStringField),
|
||||
sTableThreshold(r.sTableThreshold), forceInline(r.forceInline)
|
||||
sTableThreshold(r.sTableThreshold), forceInline(r.forceInline), userDataStore(NULL)
|
||||
{ }
|
||||
|
||||
Row::~Row() { }
|
||||
@@ -623,9 +725,10 @@ bool Row::isNullValue(uint32_t colIndex) const
|
||||
break;
|
||||
default: {
|
||||
ostringstream os;
|
||||
os << "Row::isNullValue(): got bad column type (" << types[colIndex] <<
|
||||
"). Width=" << getColumnWidth(colIndex) << endl;
|
||||
os << toString() << endl;
|
||||
os << "Row::isNullValue(): got bad column type (";
|
||||
os << types[colIndex];
|
||||
os << "). Width=";
|
||||
os << getColumnWidth(colIndex) << endl;
|
||||
throw logic_error(os.str());
|
||||
}
|
||||
}
|
||||
@@ -884,7 +987,9 @@ RowGroup & RowGroup::operator=(const RowGroup &r)
|
||||
return *this;
|
||||
}
|
||||
|
||||
RowGroup::~RowGroup() { }
|
||||
RowGroup::~RowGroup()
|
||||
{
|
||||
}
|
||||
|
||||
void RowGroup::resetRowGroup(uint64_t rid)
|
||||
{
|
||||
|
||||
110
utils/rowgroup/rowgroup.h
Normal file → Executable file
110
utils/rowgroup/rowgroup.h
Normal file → Executable file
@@ -38,6 +38,7 @@
|
||||
#include <stdexcept>
|
||||
//#define NDEBUG
|
||||
#include <cassert>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/shared_array.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <cmath>
|
||||
@@ -56,6 +57,7 @@
|
||||
#include "bytestream.h"
|
||||
#include "calpontsystemcatalog.h"
|
||||
#include "exceptclasses.h"
|
||||
#include "mcsv1_udaf.h"
|
||||
|
||||
#include "branchpred.h"
|
||||
|
||||
@@ -106,25 +108,74 @@ public:
|
||||
void clear();
|
||||
|
||||
void serialize(messageqcpp::ByteStream &) const;
|
||||
uint32_t deserialize(messageqcpp::ByteStream &);
|
||||
void deserialize(messageqcpp::ByteStream &);
|
||||
|
||||
//@bug6065, make StringStore::storeString() thread safe
|
||||
void useStoreStringMutex(bool b) { fUseStoreStringMutex = b; }
|
||||
bool useStoreStringMutex() const { return fUseStoreStringMutex; }
|
||||
|
||||
private:
|
||||
std::string empty_str;
|
||||
|
||||
StringStore(const StringStore &);
|
||||
StringStore & operator=(const StringStore &);
|
||||
static const uint32_t CHUNK_SIZE = 64*1024; // allocators like powers of 2
|
||||
|
||||
// This is an overlay b/c the underlying data needs to be any size,
|
||||
// and alloc'd in one chunk. data can't be a sepatate dynamic chunk.
|
||||
// and alloc'd in one chunk. data can't be a separate dynamic chunk.
|
||||
|
||||
std::vector<boost::shared_ptr<std::string> > mem;
|
||||
bool empty;
|
||||
bool fUseStoreStringMutex; //@bug6065, make StringStore::storeString() thread safe
|
||||
boost::mutex fMutex;
|
||||
};
|
||||
|
||||
// Where we store user data for UDA(n)F
|
||||
class UserDataStore
|
||||
{
|
||||
// length represents the fixed portion length of userData.
|
||||
// There may be variable length data in containers or other
|
||||
// user created structures.
|
||||
struct StoreData
|
||||
{
|
||||
int32_t length;
|
||||
std::string functionName;
|
||||
boost::shared_ptr<mcsv1sdk::UserData> userData;
|
||||
StoreData() : length(0) { }
|
||||
StoreData(const StoreData& rhs)
|
||||
{
|
||||
length = rhs.length;
|
||||
functionName = rhs.functionName;
|
||||
userData = rhs.userData;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
UserDataStore();
|
||||
virtual ~UserDataStore();
|
||||
|
||||
void serialize(messageqcpp::ByteStream &) const;
|
||||
void deserialize(messageqcpp::ByteStream &);
|
||||
|
||||
//Set to make UserDataStore thread safe
|
||||
void useUserDataMutex(bool b) { fUseUserDataMutex = b; }
|
||||
bool useUserDataMutex() const { return fUseUserDataMutex; }
|
||||
|
||||
// Returns the offset
|
||||
uint32_t storeUserData(mcsv1sdk::mcsv1Context& context,
|
||||
boost::shared_ptr<mcsv1sdk::UserData> data,
|
||||
uint32_t length);
|
||||
|
||||
boost::shared_ptr<mcsv1sdk::UserData> getUserData(uint32_t offset) const;
|
||||
|
||||
private:
|
||||
UserDataStore(const UserDataStore &);
|
||||
UserDataStore & operator=(const UserDataStore &);
|
||||
|
||||
std::vector<StoreData> vStoreData;
|
||||
|
||||
bool fUseUserDataMutex;
|
||||
boost::mutex fMutex;
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@@ -152,7 +203,7 @@ public:
|
||||
// the 'hasLengthField' is there b/c PM aggregation (and possibly others) currently sends
|
||||
// inline data with a length field. Once that's converted to string table format, that
|
||||
// option can go away.
|
||||
uint32_t deserialize(messageqcpp::ByteStream &, bool hasLengthField=false); // returns the # of bytes read
|
||||
void deserialize(messageqcpp::ByteStream &, bool hasLengthField=false); // returns the # of bytes read
|
||||
|
||||
inline uint64_t getStringTableMemUsage();
|
||||
void clear();
|
||||
@@ -169,9 +220,14 @@ public:
|
||||
void useStoreStringMutex(bool b) { if (strings) strings->useStoreStringMutex(b); }
|
||||
bool useStoreStringMutex() const { return (strings ? (strings->useStoreStringMutex()) : false); }
|
||||
|
||||
UserDataStore* getUserDataStore();
|
||||
// make UserDataStore::storeData() thread safe
|
||||
void useUserDataMutex(bool b) { if (userDataStore) userDataStore->useUserDataMutex(b); }
|
||||
bool useUserDataMutex() const { return (userDataStore ? (userDataStore->useUserDataMutex()) : false); }
|
||||
|
||||
boost::shared_array<uint8_t> rowData;
|
||||
boost::shared_ptr<StringStore> strings;
|
||||
|
||||
boost::shared_ptr<UserDataStore> userDataStore;
|
||||
private:
|
||||
//boost::shared_array<uint8_t> rowData;
|
||||
//boost::shared_ptr<StringStore> strings;
|
||||
@@ -187,14 +243,17 @@ class Row
|
||||
{
|
||||
public:
|
||||
struct Pointer {
|
||||
inline Pointer() : data(NULL), strings(NULL) { }
|
||||
inline Pointer() : data(NULL), strings(NULL), userDataStore(NULL) { }
|
||||
|
||||
// Pointer(uint8_t*) implicitly makes old code compatible with the string table impl;
|
||||
// make it explicit to identify things that still might need to be changed
|
||||
inline Pointer(uint8_t *d) : data(d), strings(NULL) { }
|
||||
inline Pointer(uint8_t *d, StringStore *s) : data(d), strings(s) { }
|
||||
inline Pointer(uint8_t *d) : data(d), strings(NULL), userDataStore(NULL) { }
|
||||
inline Pointer(uint8_t *d, StringStore *s) : data(d), strings(s), userDataStore(NULL) { }
|
||||
inline Pointer(uint8_t *d, StringStore *s, UserDataStore *u) :
|
||||
data(d), strings(s), userDataStore(u) { }
|
||||
uint8_t *data;
|
||||
StringStore *strings;
|
||||
UserDataStore *userDataStore;
|
||||
};
|
||||
|
||||
Row();
|
||||
@@ -290,6 +349,11 @@ class Row
|
||||
inline const uint8_t* getVarBinaryField(uint32_t& len, uint32_t colIndex) const;
|
||||
inline void setVarBinaryField(const uint8_t* val, uint32_t len, uint32_t colIndex);
|
||||
|
||||
inline boost::shared_ptr<mcsv1sdk::UserData> getUserData(uint32_t colIndex) const;
|
||||
inline void setUserData(mcsv1sdk::mcsv1Context& context,
|
||||
boost::shared_ptr<mcsv1sdk::UserData> userData,
|
||||
uint32_t len, uint32_t colIndex);
|
||||
|
||||
uint64_t getNullValue(uint32_t colIndex) const;
|
||||
bool isNullValue(uint32_t colIndex) const;
|
||||
|
||||
@@ -332,6 +396,7 @@ class Row
|
||||
inline bool equals(const Row &, uint32_t lastCol) const;
|
||||
inline bool equals(const Row &) const;
|
||||
|
||||
inline void setUserDataStore(UserDataStore* u) {userDataStore = u;}
|
||||
private:
|
||||
uint32_t columnCount;
|
||||
uint64_t baseRid;
|
||||
@@ -353,10 +418,12 @@ class Row
|
||||
boost::shared_array<bool> forceInline;
|
||||
inline bool inStringTable(uint32_t col) const;
|
||||
|
||||
UserDataStore* userDataStore; // For UDAF
|
||||
|
||||
friend class RowGroup;
|
||||
};
|
||||
|
||||
inline Row::Pointer Row::getPointer() const { return Pointer(data, strings); }
|
||||
inline Row::Pointer Row::getPointer() const { return Pointer(data, strings, userDataStore); }
|
||||
inline uint8_t * Row::getData() const { return data; }
|
||||
|
||||
inline void Row::setPointer(const Pointer &p)
|
||||
@@ -368,6 +435,7 @@ inline void Row::setPointer(const Pointer &p)
|
||||
useStringTable = hasStrings;
|
||||
offsets = (useStringTable ? stOffsets : oldOffsets);
|
||||
}
|
||||
userDataStore = p.userDataStore;
|
||||
}
|
||||
|
||||
inline void Row::setData(const Pointer &p) { setPointer(p); }
|
||||
@@ -613,6 +681,15 @@ inline const uint8_t* Row::getVarBinaryField(uint32_t& len, uint32_t colIndex) c
|
||||
}
|
||||
}
|
||||
|
||||
inline boost::shared_ptr<mcsv1sdk::UserData> Row::getUserData(uint32_t colIndex) const
|
||||
{
|
||||
if (!userDataStore)
|
||||
{
|
||||
return boost::shared_ptr<mcsv1sdk::UserData>();
|
||||
}
|
||||
return userDataStore->getUserData(*((uint32_t *) &data[offsets[colIndex]]));
|
||||
}
|
||||
|
||||
inline double Row::getDoubleField(uint32_t colIndex) const
|
||||
{
|
||||
return *((double *) &data[offsets[colIndex]]);
|
||||
@@ -783,6 +860,19 @@ inline void Row::setVarBinaryField(const uint8_t *val, uint32_t len, uint32_t co
|
||||
}
|
||||
}
|
||||
|
||||
inline void Row::setUserData(mcsv1sdk::mcsv1Context& context,
|
||||
boost::shared_ptr<mcsv1sdk::UserData> userData,
|
||||
uint32_t len, uint32_t colIndex)
|
||||
{
|
||||
if (!userDataStore)
|
||||
{
|
||||
return;
|
||||
}
|
||||
uint32_t offset = userDataStore->storeUserData(context, userData, len);
|
||||
*((uint32_t *) &data[offsets[colIndex]]) = offset;
|
||||
*((uint32_t *) &data[offsets[colIndex] + 4]) = len;
|
||||
}
|
||||
|
||||
inline void Row::copyField(uint32_t destIndex, uint32_t srcIndex) const
|
||||
{
|
||||
uint32_t n = offsets[destIndex + 1] - offsets[destIndex];
|
||||
@@ -1149,6 +1239,7 @@ inline void RowGroup::getRow(uint32_t rowNum, Row *r) const
|
||||
r->baseRid = getBaseRid();
|
||||
r->data = &(data[headerSize + (rowNum * offsets[columnCount])]);
|
||||
r->strings = strings;
|
||||
r->userDataStore = rgData->userDataStore.get();
|
||||
}
|
||||
|
||||
inline void RowGroup::setData(uint8_t *d)
|
||||
@@ -1523,13 +1614,14 @@ inline RGData & RGData::operator=(const RGData &r)
|
||||
{
|
||||
rowData = r.rowData;
|
||||
strings = r.strings;
|
||||
userDataStore = r.userDataStore;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void RGData::getRow(uint32_t num, Row *row)
|
||||
{
|
||||
uint32_t size = row->getSize();
|
||||
row->setData(Row::Pointer(&rowData[RowGroup::getHeaderSize() + (num * size)], strings.get()));
|
||||
row->setData(Row::Pointer(&rowData[RowGroup::getHeaderSize() + (num * size)], strings.get(), userDataStore.get()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
434
utils/rowgroup/rowgroup.vpj
Normal file → Executable file
434
utils/rowgroup/rowgroup.vpj
Normal file → Executable file
@@ -1,220 +1,220 @@
|
||||
<!DOCTYPE Project SYSTEM "http://www.slickedit.com/dtd/vse/10.0/vpj.dtd">
|
||||
<Project
|
||||
Version="10.0"
|
||||
VendorName="SlickEdit"
|
||||
TemplateName="GNU C/C++"
|
||||
WorkingDir=".">
|
||||
<Config
|
||||
Name="Debug"
|
||||
Type="gnuc"
|
||||
DebugCallbackName="gdb"
|
||||
Version="1"
|
||||
OutputFile="%bdrowgroup.so"
|
||||
CompilerConfigName="Latest Version">
|
||||
<Menu>
|
||||
<Target
|
||||
Name="Compile"
|
||||
MenuCaption="&Compile"
|
||||
Dialog="_gnuc_options_form Compile"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
OutputExts="*.o"
|
||||
SaveOption="SaveCurrent"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine='g++ -c %xup %defd -g -o "%bd%n%oe" %i "%f"'/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="Link"
|
||||
MenuCaption="&Link"
|
||||
ShowOnMenu="Never"
|
||||
Dialog="_gnuc_options_form Link"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
SaveOption="SaveCurrent"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine='g++ %xup -g -o "%o" %f %libs -shared -fPIC'/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="Build"
|
||||
MenuCaption="&Build"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
SaveOption="SaveWorkspaceFiles"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine="make"/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="Rebuild"
|
||||
MenuCaption="&Rebuild"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
SaveOption="SaveWorkspaceFiles"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine=""/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="Debug"
|
||||
MenuCaption="&Debug"
|
||||
Dialog="_gnuc_options_form Run/Debug"
|
||||
BuildFirst="1"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
SaveOption="SaveNone"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine=""/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="Execute"
|
||||
MenuCaption="E&xecute"
|
||||
Dialog="_gnuc_options_form Run/Debug"
|
||||
BuildFirst="1"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
SaveOption="SaveWorkspaceFiles"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine=""/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="dash"
|
||||
MenuCaption="-"
|
||||
Deletable="0">
|
||||
<Exec/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="GNU C Options"
|
||||
MenuCaption="GNU C &Options..."
|
||||
ShowOnMenu="HideIfNoCmdLine"
|
||||
Deletable="0"
|
||||
SaveOption="SaveNone">
|
||||
<Exec
|
||||
CmdLine="gnucoptions"
|
||||
Type="Slick-C"/>
|
||||
</Target>
|
||||
</Menu>
|
||||
<List Name="GNUC Options">
|
||||
<Item
|
||||
Name="LinkerOutputType"
|
||||
Value="SharedLibrary"/>
|
||||
</List>
|
||||
</Config>
|
||||
<Config
|
||||
Name="Release"
|
||||
Type="gnuc"
|
||||
DebugCallbackName="gdb"
|
||||
Version="1"
|
||||
OutputFile="%bdrowgroup.so"
|
||||
CompilerConfigName="Latest Version">
|
||||
<Menu>
|
||||
<Target
|
||||
Name="Compile"
|
||||
MenuCaption="&Compile"
|
||||
Dialog="_gnuc_options_form Compile"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
OutputExts="*.o"
|
||||
SaveOption="SaveCurrent"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine='g++ -c %xup %defd -o "%bd%n%oe" %i "%f"'/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="Link"
|
||||
MenuCaption="&Link"
|
||||
ShowOnMenu="Never"
|
||||
Dialog="_gnuc_options_form Link"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
SaveOption="SaveCurrent"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine='g++ %xup -o "%o" %f %libs -shared -fPIC'/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="Build"
|
||||
MenuCaption="&Build"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
SaveOption="SaveWorkspaceFiles"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine="make"/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="Rebuild"
|
||||
MenuCaption="&Rebuild"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
SaveOption="SaveWorkspaceFiles"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine=""/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="Debug"
|
||||
MenuCaption="&Debug"
|
||||
Dialog="_gnuc_options_form Run/Debug"
|
||||
BuildFirst="1"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
SaveOption="SaveNone"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine=""/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="Execute"
|
||||
MenuCaption="E&xecute"
|
||||
Dialog="_gnuc_options_form Run/Debug"
|
||||
BuildFirst="1"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
SaveOption="SaveWorkspaceFiles"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine=""/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="dash"
|
||||
MenuCaption="-"
|
||||
Deletable="0">
|
||||
<Exec/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="GNU C Options"
|
||||
MenuCaption="GNU C &Options..."
|
||||
ShowOnMenu="HideIfNoCmdLine"
|
||||
Deletable="0"
|
||||
SaveOption="SaveNone">
|
||||
<Exec
|
||||
CmdLine="gnucoptions"
|
||||
Type="Slick-C"/>
|
||||
</Target>
|
||||
</Menu>
|
||||
<List Name="GNUC Options">
|
||||
<Item
|
||||
Name="LinkerOutputType"
|
||||
Value="SharedLibrary"/>
|
||||
</List>
|
||||
</Config>
|
||||
<Files>
|
||||
<Folder
|
||||
Name="Source Files"
|
||||
Filters="*.c;*.C;*.cc;*.cpp;*.cp;*.cxx;*.c++;*.prg;*.pas;*.dpr;*.asm;*.s;*.bas;*.java;*.cs;*.sc;*.e;*.cob;*.html;*.rc;*.tcl;*.py;*.pl;*.d">
|
||||
<F N="rowaggregation.cpp"/>
|
||||
<F N="rowgroup.cpp"/>
|
||||
</Folder>
|
||||
<Folder
|
||||
Name="Header Files"
|
||||
Filters="*.h;*.H;*.hh;*.hpp;*.hxx;*.inc;*.sh;*.cpy;*.if">
|
||||
<F N="rowaggregation.h"/>
|
||||
<F N="rowgroup.h"/>
|
||||
</Folder>
|
||||
<Folder
|
||||
Name="Resource Files"
|
||||
Filters="*.ico;*.cur;*.dlg"/>
|
||||
<Folder
|
||||
Name="Bitmaps"
|
||||
Filters="*.bmp"/>
|
||||
<Folder
|
||||
Name="Other Files"
|
||||
Filters="">
|
||||
<F
|
||||
N="Makefile"
|
||||
Type="Makefile"/>
|
||||
</Folder>
|
||||
</Files>
|
||||
Version="10.0"
|
||||
VendorName="SlickEdit"
|
||||
TemplateName="GNU C/C++"
|
||||
WorkingDir=".">
|
||||
<Config
|
||||
Name="Debug"
|
||||
Type="gnuc"
|
||||
DebugCallbackName="gdb"
|
||||
Version="1"
|
||||
OutputFile="%bdrowgroup.so"
|
||||
CompilerConfigName="Latest Version">
|
||||
<Menu>
|
||||
<Target
|
||||
Name="Compile"
|
||||
MenuCaption="&Compile"
|
||||
Dialog="_gnuc_options_form Compile"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
OutputExts="*.o"
|
||||
SaveOption="SaveCurrent"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine='g++ -c %xup %defd -g -o "%bd%n%oe" %i "%f"'/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="Link"
|
||||
MenuCaption="&Link"
|
||||
ShowOnMenu="Never"
|
||||
Dialog="_gnuc_options_form Link"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
SaveOption="SaveCurrent"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine='g++ %xup -g -o "%o" %f %libs -shared -fPIC'/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="Build"
|
||||
MenuCaption="&Build"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
SaveOption="SaveWorkspaceFiles"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine="make"/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="Rebuild"
|
||||
MenuCaption="&Rebuild"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
SaveOption="SaveWorkspaceFiles"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine=""/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="Debug"
|
||||
MenuCaption="&Debug"
|
||||
Dialog="_gnuc_options_form Run/Debug"
|
||||
BuildFirst="1"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
SaveOption="SaveNone"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine=""/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="Execute"
|
||||
MenuCaption="E&xecute"
|
||||
Dialog="_gnuc_options_form Run/Debug"
|
||||
BuildFirst="1"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
SaveOption="SaveWorkspaceFiles"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine=""/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="dash"
|
||||
MenuCaption="-"
|
||||
Deletable="0">
|
||||
<Exec/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="GNU C Options"
|
||||
MenuCaption="GNU C &Options..."
|
||||
ShowOnMenu="HideIfNoCmdLine"
|
||||
Deletable="0"
|
||||
SaveOption="SaveNone">
|
||||
<Exec
|
||||
CmdLine="gnucoptions"
|
||||
Type="Slick-C"/>
|
||||
</Target>
|
||||
</Menu>
|
||||
<List Name="GNUC Options">
|
||||
<Item
|
||||
Name="LinkerOutputType"
|
||||
Value="SharedLibrary"/>
|
||||
</List>
|
||||
</Config>
|
||||
<Config
|
||||
Name="Release"
|
||||
Type="gnuc"
|
||||
DebugCallbackName="gdb"
|
||||
Version="1"
|
||||
OutputFile="%bdrowgroup.so"
|
||||
CompilerConfigName="Latest Version">
|
||||
<Menu>
|
||||
<Target
|
||||
Name="Compile"
|
||||
MenuCaption="&Compile"
|
||||
Dialog="_gnuc_options_form Compile"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
OutputExts="*.o"
|
||||
SaveOption="SaveCurrent"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine='g++ -c %xup %defd -o "%bd%n%oe" %i "%f"'/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="Link"
|
||||
MenuCaption="&Link"
|
||||
ShowOnMenu="Never"
|
||||
Dialog="_gnuc_options_form Link"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
SaveOption="SaveCurrent"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine='g++ %xup -o "%o" %f %libs -shared -fPIC'/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="Build"
|
||||
MenuCaption="&Build"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
SaveOption="SaveWorkspaceFiles"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine="make"/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="Rebuild"
|
||||
MenuCaption="&Rebuild"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
SaveOption="SaveWorkspaceFiles"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine=""/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="Debug"
|
||||
MenuCaption="&Debug"
|
||||
Dialog="_gnuc_options_form Run/Debug"
|
||||
BuildFirst="1"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
SaveOption="SaveNone"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine=""/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="Execute"
|
||||
MenuCaption="E&xecute"
|
||||
Dialog="_gnuc_options_form Run/Debug"
|
||||
BuildFirst="1"
|
||||
CaptureOutputWith="ProcessBuffer"
|
||||
Deletable="0"
|
||||
SaveOption="SaveWorkspaceFiles"
|
||||
RunFromDir="%rw">
|
||||
<Exec CmdLine=""/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="dash"
|
||||
MenuCaption="-"
|
||||
Deletable="0">
|
||||
<Exec/>
|
||||
</Target>
|
||||
<Target
|
||||
Name="GNU C Options"
|
||||
MenuCaption="GNU C &Options..."
|
||||
ShowOnMenu="HideIfNoCmdLine"
|
||||
Deletable="0"
|
||||
SaveOption="SaveNone">
|
||||
<Exec
|
||||
CmdLine="gnucoptions"
|
||||
Type="Slick-C"/>
|
||||
</Target>
|
||||
</Menu>
|
||||
<List Name="GNUC Options">
|
||||
<Item
|
||||
Name="LinkerOutputType"
|
||||
Value="SharedLibrary"/>
|
||||
</List>
|
||||
</Config>
|
||||
<Files>
|
||||
<Folder
|
||||
Name="Source Files"
|
||||
Filters="*.c;*.C;*.cc;*.cpp;*.cp;*.cxx;*.c++;*.prg;*.pas;*.dpr;*.asm;*.s;*.bas;*.java;*.cs;*.sc;*.e;*.cob;*.html;*.rc;*.tcl;*.py;*.pl;*.d">
|
||||
<F N="rowaggregation.cpp"/>
|
||||
<F N="rowgroup.cpp"/>
|
||||
</Folder>
|
||||
<Folder
|
||||
Name="Header Files"
|
||||
Filters="*.h;*.H;*.hh;*.hpp;*.hxx;*.inc;*.sh;*.cpy;*.if">
|
||||
<F N="rowaggregation.h"/>
|
||||
<F N="rowgroup.h"/>
|
||||
</Folder>
|
||||
<Folder
|
||||
Name="Resource Files"
|
||||
Filters="*.ico;*.cur;*.dlg"/>
|
||||
<Folder
|
||||
Name="Bitmaps"
|
||||
Filters="*.bmp"/>
|
||||
<Folder
|
||||
Name="Other Files"
|
||||
Filters="">
|
||||
<F
|
||||
N="Makefile"
|
||||
Type="Makefile"/>
|
||||
</Folder>
|
||||
</Files>
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user