1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-29 08:21:15 +03:00

Reformat all code to coding standard

This commit is contained in:
Andrew Hutchings
2017-10-26 17:18:17 +01:00
parent 4985f3456e
commit 01446d1e22
1296 changed files with 403852 additions and 353747 deletions

View File

@ -42,44 +42,52 @@ namespace windowfunction
int64_t FrameBound::getBound(int64_t b, int64_t e, int64_t c)
{
if (fBoundType == WF__UNBOUNDED_PRECEDING)
return b;
if (fBoundType == WF__UNBOUNDED_PRECEDING)
return b;
return e;
return e;
}
const string FrameBound::toString() const
{
ostringstream oss;
switch (fBoundType)
{
case WF__UNBOUNDED_PRECEDING:
oss << "unbound preceding";
break;
case WF__UNBOUNDED_FOLLOWING:
oss << "unbound following";
break;
case WF__CONSTANT_PRECEDING:
oss << "constant preceding";
break;
case WF__CONSTANT_FOLLOWING:
oss << "constant following";
break;
case WF__EXPRESSION_PRECEDING:
oss << "expression preceding";
break;
case WF__EXPRESSION_FOLLOWING:
oss << "expression following";
break;
case WF__CURRENT_ROW:
default:
oss << "current row";
break;
}
oss << endl;
ostringstream oss;
return oss.str();
switch (fBoundType)
{
case WF__UNBOUNDED_PRECEDING:
oss << "unbound preceding";
break;
case WF__UNBOUNDED_FOLLOWING:
oss << "unbound following";
break;
case WF__CONSTANT_PRECEDING:
oss << "constant preceding";
break;
case WF__CONSTANT_FOLLOWING:
oss << "constant following";
break;
case WF__EXPRESSION_PRECEDING:
oss << "expression preceding";
break;
case WF__EXPRESSION_FOLLOWING:
oss << "expression following";
break;
case WF__CURRENT_ROW:
default:
oss << "current row";
break;
}
oss << endl;
return oss.str();
}

View File

@ -55,65 +55,96 @@ const int WF__BOUND_ROLLING = -2; // unbounded - current row
class FrameBound
{
public:
/** @brief FrameBound constructor
* @param t, frame type
*/
FrameBound(int t = 0) : fBoundType(t), fStart(true) {};
/** @brief FrameBound constructor
* @param t, frame type
*/
FrameBound(int t = 0) : fBoundType(t), fStart(true) {};
/** @brief FrameBound destructor
*/
virtual ~FrameBound() {};
/** @brief FrameBound destructor
*/
virtual ~FrameBound() {};
/** @brief clone
*/
virtual FrameBound* clone()
{ return new FrameBound(*this); }
/** @brief clone
*/
virtual FrameBound* clone()
{
return new FrameBound(*this);
}
/** @brief virtual void getBound
* @param b: partition start position
* @param e: partition end position
* @param c: current position
* @return : frame position
*/
virtual int64_t getBound(int64_t b, int64_t e, int64_t c);
/** @brief virtual void getBound
* @param b: partition start position
* @param e: partition end position
* @param c: current position
* @return : frame position
*/
virtual int64_t getBound(int64_t b, int64_t e, int64_t c);
virtual const std::string toString() const;
virtual const std::string toString() const;
void setRowData(const boost::shared_ptr<std::vector<joblist::RowPosition> >& d) {fRowData = d;}
void setRowMetaData(const rowgroup::RowGroup& g, const rowgroup::Row& r)
{ fRowGroup = g; fRow = r; }
void setRowData(const boost::shared_ptr<std::vector<joblist::RowPosition> >& d)
{
fRowData = d;
}
void setRowMetaData(const rowgroup::RowGroup& g, const rowgroup::Row& r)
{
fRowGroup = g;
fRow = r;
}
int64_t boundType() const { return fBoundType; }
void boundType(int64_t t) { fBoundType = t; }
int64_t boundType() const
{
return fBoundType;
}
void boundType(int64_t t)
{
fBoundType = t;
}
bool start() const { return fStart; }
void start(bool s) { fStart = s; }
bool start() const
{
return fStart;
}
void start(bool s)
{
fStart = s;
}
const boost::shared_ptr<ordering::EqualCompData>& peer() const { return fPeer; }
void peer(const boost::shared_ptr<ordering::EqualCompData>& p) { fPeer = p; }
const boost::shared_ptr<ordering::EqualCompData>& peer() const
{
return fPeer;
}
void peer(const boost::shared_ptr<ordering::EqualCompData>& p)
{
fPeer = p;
}
// for string table
void setCallback(joblist::WindowFunctionStep* step) { fStep = step; }
rowgroup::Row::Pointer getPointer(joblist::RowPosition& r)
{ return fStep->getPointer(r, fRowGroup, fRow); }
// for string table
void setCallback(joblist::WindowFunctionStep* step)
{
fStep = step;
}
rowgroup::Row::Pointer getPointer(joblist::RowPosition& r)
{
return fStep->getPointer(r, fRowGroup, fRow);
}
protected:
// boundary type
int64_t fBoundType;
bool fStart;
// boundary type
int64_t fBoundType;
bool fStart;
// data
boost::shared_ptr<std::vector<joblist::RowPosition> > fRowData;
// data
boost::shared_ptr<std::vector<joblist::RowPosition> > fRowData;
// row meta data
rowgroup::RowGroup fRowGroup;
rowgroup::Row fRow;
// row meta data
rowgroup::RowGroup fRowGroup;
rowgroup::Row fRow;
// functor for peer checking
boost::shared_ptr<ordering::EqualCompData> fPeer;
// functor for peer checking
boost::shared_ptr<ordering::EqualCompData> fPeer;
// pointer back to step
joblist::WindowFunctionStep* fStep;
// pointer back to step
joblist::WindowFunctionStep* fStep;
};

View File

@ -42,314 +42,322 @@ namespace windowfunction
int64_t FrameBoundRange::getBound(int64_t b, int64_t e, int64_t c)
{
if (fStart)
{
while (c > b)
{
if (!fPeer->operator()(getPointer(fRowData->at(c)), getPointer(fRowData->at(c-1))))
break;
if (fStart)
{
while (c > b)
{
if (!fPeer->operator()(getPointer(fRowData->at(c)), getPointer(fRowData->at(c - 1))))
break;
c--;
}
}
else
{
while (c < e)
{
if (!fPeer->operator()(getPointer(fRowData->at(c)), getPointer(fRowData->at(c+1))))
break;
c--;
}
}
else
{
while (c < e)
{
if (!fPeer->operator()(getPointer(fRowData->at(c)), getPointer(fRowData->at(c + 1))))
break;
c++;
}
}
c++;
}
}
return c;
return c;
}
const string FrameBoundRange::toString() const
{
return FrameBound::toString();
return FrameBound::toString();
}
template<typename T>
int64_t FrameBoundConstantRange<T>::getBound(int64_t b, int64_t e, int64_t c)
{
// set row data
fRow.setData(getPointer(fRowData->at(c)));
getValue(fValue, fIndex[2]);
// set row data
fRow.setData(getPointer(fRowData->at(c)));
getValue(fValue, fIndex[2]);
// make sure the expr is not negative
validate();
// make sure the expr is not negative
validate();
// calculate the offset, and move
if (fIsZero)
c = FrameBoundRange::getBound(b, e, c);
else if (fBoundType < WF__CURRENT_ROW)
c -= getPrecedingOffset(c, b);
else
c += getFollowingOffset(c, e);
// calculate the offset, and move
if (fIsZero)
c = FrameBoundRange::getBound(b, e, c);
else if (fBoundType < WF__CURRENT_ROW)
c -= getPrecedingOffset(c, b);
else
c += getFollowingOffset(c, e);
return c;
return c;
}
template<typename T>
int64_t FrameBoundConstantRange<T>::getPrecedingOffset(int64_t c, int64_t b)
{
// test each row to find the bound
bool next = true;
int64_t i = c;
int64_t j = 0;
// test each row to find the bound
bool next = true;
int64_t i = c;
int64_t j = 0;
for (i--, j++; i >= b && next; i--, j++)
{
// set row data, get order by column value
fRow.setData(getPointer(fRowData->at(i)));
ValueType<T> v;
getValue(v, fIndex[0]);
if (v.fIsNull)
{
next = fValue.fIsNull; // let null = null
}
else if (fValue.fIsNull)
{
next = false;
}
else if (fAsc && v.fValue < fValue.fValue)
{
next = false;
}
else if (!fAsc && v.fValue > fValue.fValue)
{
next = false;
}
else if (!fStart && v.fValue == fValue.fValue)
{
next = false;
}
}
for (i--, j++; i >= b && next; i--, j++)
{
// set row data, get order by column value
fRow.setData(getPointer(fRowData->at(i)));
ValueType<T> v;
getValue(v, fIndex[0]);
if (!next)
{
if (fStart)
j -= 2;
else
j -= 1;
}
if (v.fIsNull)
{
next = fValue.fIsNull; // let null = null
}
else if (fValue.fIsNull)
{
next = false;
}
else if (fAsc && v.fValue < fValue.fValue)
{
next = false;
}
else if (!fAsc && v.fValue > fValue.fValue)
{
next = false;
}
else if (!fStart && v.fValue == fValue.fValue)
{
next = false;
}
}
return j;
if (!next)
{
if (fStart)
j -= 2;
else
j -= 1;
}
return j;
}
template<typename T>
int64_t FrameBoundConstantRange<T>::getFollowingOffset(int64_t c, int64_t e)
{
// test each row to find the bound
bool next = true;
int64_t i = c;
int64_t j = 0;
// test each row to find the bound
bool next = true;
int64_t i = c;
int64_t j = 0;
for (i++, j++; i <= e && next; i++, j++)
{
// set row data, get order by column value
fRow.setData(getPointer(fRowData->at(i)));
ValueType<T> v;
getValue(v, fIndex[0]);
if (v.fIsNull)
{
next = fValue.fIsNull; // let null = null
}
else if (fValue.fIsNull)
{
next = false;
}
else if (fAsc && v.fValue > fValue.fValue)
{
next = false;
}
else if (!fAsc && v.fValue < fValue.fValue)
{
next = false;
}
else if (fStart && v.fValue == fValue.fValue)
{
next = false;
}
}
for (i++, j++; i <= e && next; i++, j++)
{
// set row data, get order by column value
fRow.setData(getPointer(fRowData->at(i)));
ValueType<T> v;
getValue(v, fIndex[0]);
if (!next)
{
if (fStart)
j -= 1;
else
j -= 2;
}
if (v.fIsNull)
{
next = fValue.fIsNull; // let null = null
}
else if (fValue.fIsNull)
{
next = false;
}
else if (fAsc && v.fValue > fValue.fValue)
{
next = false;
}
else if (!fAsc && v.fValue < fValue.fValue)
{
next = false;
}
else if (fStart && v.fValue == fValue.fValue)
{
next = false;
}
}
return j;
if (!next)
{
if (fStart)
j -= 1;
else
j -= 2;
}
return j;
}
template<typename T>
void FrameBoundConstantRange<T>::getValue(ValueType<T>& v, int64_t i)
{
v.fIsNull = fRow.isNullValue(i);
if (!v.fIsNull)
v.fValue = fRow.getIntField(i);
v.fIsNull = fRow.isNullValue(i);
if (!v.fIsNull)
v.fValue = fRow.getIntField(i);
}
template<typename T>
T FrameBoundConstantRange<T>::getValueByType(int64_t i)
{
T t;
return t;
T t;
return t;
}
template<> int64_t FrameBoundConstantRange<int64_t>::getValueByType(int64_t i)
{
return fRow.getIntField(i);
return fRow.getIntField(i);
}
template<> uint64_t FrameBoundConstantRange<uint64_t>::getValueByType(int64_t i)
{
uint64_t v = fRow.getUintField(i);
uint64_t v = fRow.getUintField(i);
// convert date to datetime, [refer to treenode.h]
if (fRow.getColType(fIndex[0]) == execplan::CalpontSystemCatalog::DATE && i == 0)
v = v << 32;
// convert date to datetime, [refer to treenode.h]
if (fRow.getColType(fIndex[0]) == execplan::CalpontSystemCatalog::DATE && i == 0)
v = v << 32;
return v;
return v;
}
template<> double FrameBoundConstantRange<double>::getValueByType(int64_t i)
{
return fRow.getDoubleField(i);
return fRow.getDoubleField(i);
}
template<> float FrameBoundConstantRange<float>::getValueByType(int64_t i)
{
return fRow.getFloatField(i);
return fRow.getFloatField(i);
}
template<typename T>
const string FrameBoundConstantRange<T>::toString() const
{
ostringstream oss;
oss << fValue.fValue << " " << FrameBound::toString();
return oss.str();
ostringstream oss;
oss << fValue.fValue << " " << FrameBound::toString();
return oss.str();
}
template<typename T>
int64_t FrameBoundExpressionRange<T>::getPrecedingOffset(int64_t c, int64_t b)
{
return FrameBoundConstantRange<T>::getPrecedingOffset(c, b);
return FrameBoundConstantRange<T>::getPrecedingOffset(c, b);
}
template<typename T>
int64_t FrameBoundExpressionRange<T>::getFollowingOffset(int64_t c, int64_t e)
{
return FrameBoundConstantRange<T>::getFollowingOffset(c, e);
return FrameBoundConstantRange<T>::getFollowingOffset(c, e);
}
template<typename T>
void FrameBoundExpressionRange<T>::validate()
{
bool invalid = false;
ostringstream oss;
bool invalid = false;
ostringstream oss;
if (this->fRow.isNullValue(this->fIndex[1]))
{
invalid = true;
oss << "NULL";
}
else
{
switch (this->fRow.getColType(this->fIndex[1]))
{
case execplan::CalpontSystemCatalog::TINYINT:
case execplan::CalpontSystemCatalog::SMALLINT:
case execplan::CalpontSystemCatalog::MEDINT:
case execplan::CalpontSystemCatalog::INT:
case execplan::CalpontSystemCatalog::BIGINT:
case execplan::CalpontSystemCatalog::DECIMAL:
{
int64_t tmp = this->fRow.getIntField(this->fIndex[1]);
this->fIsZero = (tmp == 0);
if (tmp < 0)
{
invalid = true;
oss << tmp;
}
if (this->fRow.isNullValue(this->fIndex[1]))
{
invalid = true;
oss << "NULL";
}
else
{
switch (this->fRow.getColType(this->fIndex[1]))
{
case execplan::CalpontSystemCatalog::TINYINT:
case execplan::CalpontSystemCatalog::SMALLINT:
case execplan::CalpontSystemCatalog::MEDINT:
case execplan::CalpontSystemCatalog::INT:
case execplan::CalpontSystemCatalog::BIGINT:
case execplan::CalpontSystemCatalog::DECIMAL:
{
int64_t tmp = this->fRow.getIntField(this->fIndex[1]);
this->fIsZero = (tmp == 0);
break;
}
if (tmp < 0)
{
invalid = true;
oss << tmp;
}
case execplan::CalpontSystemCatalog::DOUBLE:
case execplan::CalpontSystemCatalog::UDOUBLE:
{
double tmp = this->fRow.getDoubleField(this->fIndex[1]);
this->fIsZero = (tmp == 0.0);
if (tmp < 0)
{
invalid = true;
oss << tmp;
}
break;
}
break;
}
case execplan::CalpontSystemCatalog::FLOAT:
case execplan::CalpontSystemCatalog::UFLOAT:
{
float tmp = this->fRow.getFloatField(this->fIndex[1]);
this->fIsZero = (tmp == 0.0);
if (tmp < 0)
{
invalid = true;
oss << tmp;
}
break;
}
case execplan::CalpontSystemCatalog::DOUBLE:
case execplan::CalpontSystemCatalog::UDOUBLE:
{
double tmp = this->fRow.getDoubleField(this->fIndex[1]);
this->fIsZero = (tmp == 0.0);
case execplan::CalpontSystemCatalog::UTINYINT:
case execplan::CalpontSystemCatalog::USMALLINT:
case execplan::CalpontSystemCatalog::UMEDINT:
case execplan::CalpontSystemCatalog::UINT:
case execplan::CalpontSystemCatalog::UBIGINT:
case execplan::CalpontSystemCatalog::UDECIMAL:
default:
{
int64_t tmp = this->fRow.getIntField(this->fIndex[1]);
this->fIsZero = (tmp == 0);
break;
}
}
}
if (tmp < 0)
{
invalid = true;
oss << tmp;
}
if (invalid)
{
oss << " (expr)";
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ERR_WF_BOUND_OUT_OF_RANGE, oss.str()),
ERR_WF_BOUND_OUT_OF_RANGE);
}
break;
}
case execplan::CalpontSystemCatalog::FLOAT:
case execplan::CalpontSystemCatalog::UFLOAT:
{
float tmp = this->fRow.getFloatField(this->fIndex[1]);
this->fIsZero = (tmp == 0.0);
if (tmp < 0)
{
invalid = true;
oss << tmp;
}
break;
}
case execplan::CalpontSystemCatalog::UTINYINT:
case execplan::CalpontSystemCatalog::USMALLINT:
case execplan::CalpontSystemCatalog::UMEDINT:
case execplan::CalpontSystemCatalog::UINT:
case execplan::CalpontSystemCatalog::UBIGINT:
case execplan::CalpontSystemCatalog::UDECIMAL:
default:
{
int64_t tmp = this->fRow.getIntField(this->fIndex[1]);
this->fIsZero = (tmp == 0);
break;
}
}
}
if (invalid)
{
oss << " (expr)";
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ERR_WF_BOUND_OUT_OF_RANGE, oss.str()),
ERR_WF_BOUND_OUT_OF_RANGE);
}
}
template<typename T>
const string FrameBoundExpressionRange<T>::toString() const
{
ostringstream oss;
oss << " value_expr " << FrameBound::toString();
return oss.str();
ostringstream oss;
oss << " value_expr " << FrameBound::toString();
return oss.str();
}

View File

@ -35,52 +35,73 @@ namespace windowfunction
class FrameBoundRange : public FrameBound
{
public:
/** @brief FrameBoundRange constructor
* @param t, frame type
* @param a, order by sort spec: asc | desc
* @param n, order by sort spec: null first | null last
* @param v, order by column data type
*/
FrameBoundRange(int t = 0, bool a = true, bool n = true)
: FrameBound(t), fAsc(a), fNullFirst(n), fIsZero(false) {};
/** @brief FrameBoundRange constructor
* @param t, frame type
* @param a, order by sort spec: asc | desc
* @param n, order by sort spec: null first | null last
* @param v, order by column data type
*/
FrameBoundRange(int t = 0, bool a = true, bool n = true)
: FrameBound(t), fAsc(a), fNullFirst(n), fIsZero(false) {};
/** @brief FrameBoundRange destructor
*/
virtual ~FrameBoundRange() {};
/** @brief FrameBoundRange destructor
*/
virtual ~FrameBoundRange() {};
/** @brief clone
*/
virtual FrameBound* clone() { return NULL; } // abstract class
/** @brief clone
*/
virtual FrameBound* clone()
{
return NULL; // abstract class
}
/** @brief virtual void getBound
*/
int64_t getBound(int64_t, int64_t, int64_t);
/** @brief virtual void getBound
*/
int64_t getBound(int64_t, int64_t, int64_t);
const std::string toString() const;
const std::string toString() const;
void setTupleId(std::vector<uint64_t> ids) { fTupleId = ids; }
std::vector<uint64_t> getTupleId() const { return fTupleId; }
void setTupleId(std::vector<uint64_t> ids)
{
fTupleId = ids;
}
std::vector<uint64_t> getTupleId() const
{
return fTupleId;
}
void setIndex(vector<int> idx) { fIndex = idx; }
const std::vector<int>& getIndex() const { return fIndex; }
void setIndex(vector<int> idx)
{
fIndex = idx;
}
const std::vector<int>& getIndex() const
{
return fIndex;
}
void isZero(bool z) { fIsZero = z; }
bool isZero() const { return fIsZero; }
void isZero(bool z)
{
fIsZero = z;
}
bool isZero() const
{
return fIsZero;
}
protected:
// for range calculation
// data, row meta data, order by column index, ascending | descending
// [0]: order by; [1]: interval; [2]: [0] +/- [1]
std::vector<uint64_t> fTupleId;
std::vector<int> fIndex;
// for range calculation
// data, row meta data, order by column index, ascending | descending
// [0]: order by; [1]: interval; [2]: [0] +/- [1]
std::vector<uint64_t> fTupleId;
std::vector<int> fIndex;
// order by sort specification
bool fAsc;
bool fNullFirst;
// order by sort specification
bool fAsc;
bool fNullFirst;
// in case expr evaluates to 0
bool fIsZero;
// in case expr evaluates to 0
bool fIsZero;
};
@ -91,11 +112,11 @@ protected:
template<typename T>
struct ValueType
{
T fValue;
bool fIsNull;
T fValue;
bool fIsNull;
// constructor
ValueType() : fValue(0), fIsNull(false) {}
// constructor
ValueType() : fValue(0), fIsNull(false) {}
};
@ -106,53 +127,56 @@ template<typename T>
class FrameBoundConstantRange : public FrameBoundRange
{
public:
/** @brief FrameBoundConstant constructor
* @param t, frame type
* @param a, order by sort spec: asc | desc
* @param n, order by sort spec: null first | null last
* @param c, constant value. !! caller need to check NULL or negative value !!
*/
FrameBoundConstantRange(int t = 0, bool a = true, bool n = true, void* c = NULL)
: FrameBoundRange(t, a, n)
{
fValue.fIsNull = (c == NULL);
if (!fValue.fIsNull)
fValue.fValue = *((T*) c);
};
/** @brief FrameBoundConstant constructor
* @param t, frame type
* @param a, order by sort spec: asc | desc
* @param n, order by sort spec: null first | null last
* @param c, constant value. !! caller need to check NULL or negative value !!
*/
FrameBoundConstantRange(int t = 0, bool a = true, bool n = true, void* c = NULL)
: FrameBoundRange(t, a, n)
{
fValue.fIsNull = (c == NULL);
/** @brief FrameBoundConstantRange destructor
*/
virtual ~FrameBoundConstantRange() {};
if (!fValue.fIsNull)
fValue.fValue = *((T*) c);
};
/** @brief clone
*/
virtual FrameBound* clone()
{ return new FrameBoundConstantRange(*this); }
/** @brief FrameBoundConstantRange destructor
*/
virtual ~FrameBoundConstantRange() {};
/** @brief virtual void getBound
*/
int64_t getBound(int64_t, int64_t, int64_t);
/** @brief clone
*/
virtual FrameBound* clone()
{
return new FrameBoundConstantRange(*this);
}
const std::string toString() const;
/** @brief virtual void getBound
*/
int64_t getBound(int64_t, int64_t, int64_t);
const std::string toString() const;
protected:
// find the range offset
// i: partition upper bound
// find the range offset
// i: partition upper bound
// j: current row
// k: partition lower bound
virtual int64_t getPrecedingOffset(int64_t j, int64_t i);
virtual int64_t getFollowingOffset(int64_t j, int64_t k);
// k: partition lower bound
virtual int64_t getPrecedingOffset(int64_t j, int64_t i);
virtual int64_t getFollowingOffset(int64_t j, int64_t k);
// validate value is not negative
virtual void validate() {}
// validate value is not negative
virtual void validate() {}
// get value at fIndex[x]
void getValue(ValueType<T>&, int64_t);
T getValueByType(int64_t);
// get value at fIndex[x]
void getValue(ValueType<T>&, int64_t);
T getValueByType(int64_t);
// order by column value type
ValueType<T> fValue;
// order by column value type
ValueType<T> fValue;
};
@ -164,39 +188,41 @@ template<typename T>
class FrameBoundExpressionRange : public FrameBoundConstantRange<T>
{
public:
/** @brief FrameBoundExpressionRange constructor
* @param t, frame type
* @param a, order by sort spec: asc | desc
* @param n, order by sort spec: null first | null last
*/
FrameBoundExpressionRange(int t = 0, bool a = true, bool n = true) :
FrameBoundConstantRange<T>(t, a, n) {};
/** @brief FrameBoundExpressionRange constructor
* @param t, frame type
* @param a, order by sort spec: asc | desc
* @param n, order by sort spec: null first | null last
*/
FrameBoundExpressionRange(int t = 0, bool a = true, bool n = true) :
FrameBoundConstantRange<T>(t, a, n) {};
/** @brief FrameBoundExpressionRange destructor
*/
virtual ~FrameBoundExpressionRange() {};
/** @brief FrameBoundExpressionRange destructor
*/
virtual ~FrameBoundExpressionRange() {};
/** @brief clone
*/
virtual FrameBound* clone()
{ return new FrameBoundExpressionRange(*this); }
/** @brief clone
*/
virtual FrameBound* clone()
{
return new FrameBoundExpressionRange(*this);
}
/** @brief virtual void getBound
*/
// int64_t getBound(int64_t, int64_t, int64_t);
/** @brief virtual void getBound
*/
// int64_t getBound(int64_t, int64_t, int64_t);
const std::string toString() const;
const std::string toString() const;
protected:
// virtual in FrameBoundRange
int64_t getPrecedingOffset(int64_t j, int64_t i);
int64_t getFollowingOffset(int64_t j, int64_t k);
// virtual in FrameBoundRange
int64_t getPrecedingOffset(int64_t j, int64_t i);
int64_t getFollowingOffset(int64_t j, int64_t k);
// validate the expression is not negative
void validate();
// validate the expression is not negative
void validate();
};

View File

@ -43,65 +43,65 @@ namespace windowfunction
int64_t FrameBoundRow::getBound(int64_t b, int64_t e, int64_t c)
{
return c;
return c;
}
const string FrameBoundRow::toString() const
{
return FrameBound::toString();
return FrameBound::toString();
}
int64_t FrameBoundConstantRow::getBound(int64_t b, int64_t e, int64_t c)
{
if (fBoundType < WF__CURRENT_ROW)
{
if (fOffset <= (c - b))
c -= fOffset;
else
c = b - (!fStart ? 1 : 0);
}
else
{
if (fOffset <= (e - c))
c += fOffset;
else
c = e + (fStart ? 1 : 0);
}
if (fBoundType < WF__CURRENT_ROW)
{
if (fOffset <= (c - b))
c -= fOffset;
else
c = b - (!fStart ? 1 : 0);
}
else
{
if (fOffset <= (e - c))
c += fOffset;
else
c = e + (fStart ? 1 : 0);
}
return c;
return c;
}
const string FrameBoundConstantRow::toString() const
{
ostringstream oss;
oss << fOffset << " " << FrameBound::toString();
return oss.str();
oss << fOffset << " " << FrameBound::toString();
return oss.str();
}
template<typename T>
int64_t FrameBoundExpressionRow<T>::getBound(int64_t b, int64_t e, int64_t c)
{
// set row data
// get expression int value
fRow.setData(getPointer(fRowData->at(c)));
// set row data
// get expression int value
fRow.setData(getPointer(fRowData->at(c)));
if (fRow.isNullValue(fExprIdx))
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ERR_WF_BOUND_OUT_OF_RANGE, "NULL"),
ERR_WF_BOUND_OUT_OF_RANGE);
if (fRow.isNullValue(fExprIdx))
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ERR_WF_BOUND_OUT_OF_RANGE, "NULL"),
ERR_WF_BOUND_OUT_OF_RANGE);
getOffset();
getOffset();
if (fOffset < 0)
{
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ERR_WF_BOUND_OUT_OF_RANGE, fOffset),
ERR_WF_BOUND_OUT_OF_RANGE);
}
if (fOffset < 0)
{
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ERR_WF_BOUND_OUT_OF_RANGE, fOffset),
ERR_WF_BOUND_OUT_OF_RANGE);
}
return FrameBoundConstantRow::getBound(b, e, c);
return FrameBoundConstantRow::getBound(b, e, c);
}
@ -109,8 +109,8 @@ template<typename T>
const string FrameBoundExpressionRow<T>::toString() const
{
ostringstream oss;
oss << "value_expr " << FrameBound::toString();
return oss.str();
oss << "value_expr " << FrameBound::toString();
return oss.str();
}
@ -121,25 +121,25 @@ template<typename T> void FrameBoundExpressionRow<T>::getOffset()
template<> void FrameBoundExpressionRow<int64_t>::getOffset()
{
fOffset = fRow.getIntField(fExprIdx);
fOffset = fRow.getIntField(fExprIdx);
}
template<> void FrameBoundExpressionRow<uint64_t>::getOffset()
{
fOffset = fRow.getUintField(fExprIdx);
fOffset = fRow.getUintField(fExprIdx);
}
template<> void FrameBoundExpressionRow<double>::getOffset()
{
fOffset = (int64_t) fRow.getDoubleField(fExprIdx);
fOffset = (int64_t) fRow.getDoubleField(fExprIdx);
}
template<> void FrameBoundExpressionRow<float>::getOffset()
{
fOffset = (int64_t) fRow.getFloatField(fExprIdx);
fOffset = (int64_t) fRow.getFloatField(fExprIdx);
}

View File

@ -35,25 +35,27 @@ namespace windowfunction
class FrameBoundRow : public FrameBound
{
public:
/** @brief FrameBoundRow constructor
* @param t, frame type
*/
FrameBoundRow(int t = 0) : FrameBound(t) {};
/** @brief FrameBoundRow constructor
* @param t, frame type
*/
FrameBoundRow(int t = 0) : FrameBound(t) {};
/** @brief FrameBoundRow destructor
*/
virtual ~FrameBoundRow() {};
/** @brief FrameBoundRow destructor
*/
virtual ~FrameBoundRow() {};
/** @brief clone
*/
virtual FrameBound* clone()
{ return new FrameBoundRow(*this); }
/** @brief clone
*/
virtual FrameBound* clone()
{
return new FrameBoundRow(*this);
}
/** @brief virtual void getBound
*/
int64_t getBound(int64_t, int64_t, int64_t);
/** @brief virtual void getBound
*/
int64_t getBound(int64_t, int64_t, int64_t);
const std::string toString() const;
const std::string toString() const;
protected:
@ -67,32 +69,34 @@ protected:
class FrameBoundConstantRow : public FrameBoundRow
{
public:
/** @brief FrameBoundConstant constructor
* @param t, frame type
* @param c, constant value. !! caller need to check NULL or negative value !!
*/
FrameBoundConstantRow(int t = 0, int c = 0) : FrameBoundRow(t), fOffset(c) {};
/** @brief FrameBoundConstant constructor
* @param t, frame type
* @param c, constant value. !! caller need to check NULL or negative value !!
*/
FrameBoundConstantRow(int t = 0, int c = 0) : FrameBoundRow(t), fOffset(c) {};
/** @brief FrameBoundConstantRow destructor
*/
virtual ~FrameBoundConstantRow() {};
/** @brief FrameBoundConstantRow destructor
*/
virtual ~FrameBoundConstantRow() {};
/** @brief clone
*/
virtual FrameBound* clone()
{ return new FrameBoundConstantRow(*this); }
/** @brief clone
*/
virtual FrameBound* clone()
{
return new FrameBoundConstantRow(*this);
}
/** @brief virtual void getBound
*/
int64_t getBound(int64_t, int64_t, int64_t);
/** @brief virtual void getBound
*/
int64_t getBound(int64_t, int64_t, int64_t);
const std::string toString() const;
const std::string toString() const;
protected:
// constant offset
int64_t fOffset;
// constant offset
int64_t fOffset;
};
@ -104,41 +108,55 @@ template<typename T>
class FrameBoundExpressionRow : public FrameBoundConstantRow
{
public:
/** @brief FrameBoundExpressionRow constructor
* @param t, frame type
*/
FrameBoundExpressionRow(int t, uint64_t id = -1, int idx = -1) :
FrameBoundConstantRow(t), fExprTupleId(id), fExprIdx(idx) {};
/** @brief FrameBoundExpressionRow constructor
* @param t, frame type
*/
FrameBoundExpressionRow(int t, uint64_t id = -1, int idx = -1) :
FrameBoundConstantRow(t), fExprTupleId(id), fExprIdx(idx) {};
/** @brief FrameBoundExpressionRow destructor
*/
virtual ~FrameBoundExpressionRow() {};
/** @brief FrameBoundExpressionRow destructor
*/
virtual ~FrameBoundExpressionRow() {};
/** @brief clone
*/
virtual FrameBound* clone()
{ return new FrameBoundExpressionRow<T>(*this); }
/** @brief clone
*/
virtual FrameBound* clone()
{
return new FrameBoundExpressionRow<T>(*this);
}
/** @brief virtual void getBound
*/
int64_t getBound(int64_t, int64_t, int64_t);
/** @brief virtual void getBound
*/
int64_t getBound(int64_t, int64_t, int64_t);
const std::string toString() const;
const std::string toString() const;
void setExprTupleId(int id) { fExprTupleId = id; }
uint64_t getExprTupleId() const { return fExprTupleId; }
void setExprTupleId(int id)
{
fExprTupleId = id;
}
uint64_t getExprTupleId() const
{
return fExprTupleId;
}
void setExprIndex(int i) { fExprIdx = i; }
uint64_t getExprIndex() const { return fExprIdx; }
void setExprIndex(int i)
{
fExprIdx = i;
}
uint64_t getExprIndex() const
{
return fExprIdx;
}
protected:
void getOffset();
void getOffset();
// id and index in row
uint64_t fExprTupleId;
int fExprIdx;
// id and index in row
uint64_t fExprTupleId;
int fExprIdx;
};

View File

@ -49,199 +49,201 @@ namespace ordering
int IntCompare::operator()(IdbCompare* l, Row::Pointer r1, Row::Pointer r2)
{
l->row1().setData(r1);
l->row2().setData(r2);
l->row1().setData(r1);
l->row2().setData(r2);
bool b1 = l->row1().isNullValue(fSpec.fIndex);
bool b2 = l->row2().isNullValue(fSpec.fIndex);
bool b1 = l->row1().isNullValue(fSpec.fIndex);
bool b2 = l->row2().isNullValue(fSpec.fIndex);
int ret = 0;
int ret = 0;
if (b1 == true || b2 == true)
{
if (b1 == false && b2 == true)
ret = fSpec.fNf;
else if (b1 == true && b2 == false)
ret = -fSpec.fNf;
}
else
{
int64_t v1 = l->row1().getIntField(fSpec.fIndex);
int64_t v2 = l->row2().getIntField(fSpec.fIndex);
if (b1 == true || b2 == true)
{
if (b1 == false && b2 == true)
ret = fSpec.fNf;
else if (b1 == true && b2 == false)
ret = -fSpec.fNf;
}
else
{
int64_t v1 = l->row1().getIntField(fSpec.fIndex);
int64_t v2 = l->row2().getIntField(fSpec.fIndex);
if (v1 > v2)
ret = fSpec.fAsc;
else if (v1 < v2)
ret = -fSpec.fAsc;
}
if (v1 > v2)
ret = fSpec.fAsc;
else if (v1 < v2)
ret = -fSpec.fAsc;
}
return ret;
return ret;
}
int UintCompare::operator()(IdbCompare* l, Row::Pointer r1, Row::Pointer r2)
{
l->row1().setData(r1);
l->row2().setData(r2);
l->row1().setData(r1);
l->row2().setData(r2);
bool b1 = l->row1().isNullValue(fSpec.fIndex);
bool b2 = l->row2().isNullValue(fSpec.fIndex);
bool b1 = l->row1().isNullValue(fSpec.fIndex);
bool b2 = l->row2().isNullValue(fSpec.fIndex);
int ret = 0;
int ret = 0;
if (b1 == true || b2 == true)
{
if (b1 == false && b2 == true)
ret = fSpec.fNf;
else if (b1 == true && b2 == false)
ret = -fSpec.fNf;
}
else
{
uint64_t v1 = l->row1().getUintField(fSpec.fIndex);
uint64_t v2 = l->row2().getUintField(fSpec.fIndex);
if (b1 == true || b2 == true)
{
if (b1 == false && b2 == true)
ret = fSpec.fNf;
else if (b1 == true && b2 == false)
ret = -fSpec.fNf;
}
else
{
uint64_t v1 = l->row1().getUintField(fSpec.fIndex);
uint64_t v2 = l->row2().getUintField(fSpec.fIndex);
if (v1 > v2)
ret = fSpec.fAsc;
else if (v1 < v2)
ret = -fSpec.fAsc;
}
if (v1 > v2)
ret = fSpec.fAsc;
else if (v1 < v2)
ret = -fSpec.fAsc;
}
return ret;
return ret;
}
int StringCompare::operator()(IdbCompare* l, Row::Pointer r1, Row::Pointer r2)
{
l->row1().setData(r1);
l->row2().setData(r2);
l->row1().setData(r1);
l->row2().setData(r2);
bool b1 = l->row1().isNullValue(fSpec.fIndex);
bool b2 = l->row2().isNullValue(fSpec.fIndex);
bool b1 = l->row1().isNullValue(fSpec.fIndex);
bool b2 = l->row2().isNullValue(fSpec.fIndex);
int ret = 0;
int ret = 0;
if (b1 == true || b2 == true)
{
if (b1 == false && b2 == true)
ret = fSpec.fNf;
else if (b1 == true && b2 == false)
ret = -fSpec.fNf;
}
else
{
string v1 = l->row1().getStringField(fSpec.fIndex);
string v2 = l->row2().getStringField(fSpec.fIndex);
if (b1 == true || b2 == true)
{
if (b1 == false && b2 == true)
ret = fSpec.fNf;
else if (b1 == true && b2 == false)
ret = -fSpec.fNf;
}
else
{
string v1 = l->row1().getStringField(fSpec.fIndex);
string v2 = l->row2().getStringField(fSpec.fIndex);
if (v1 > v2)
ret = fSpec.fAsc;
else if (v1 < v2)
ret = -fSpec.fAsc;
}
if (v1 > v2)
ret = fSpec.fAsc;
else if (v1 < v2)
ret = -fSpec.fAsc;
}
return ret;
return ret;
}
int DoubleCompare::operator()(IdbCompare* l, Row::Pointer r1, Row::Pointer r2)
{
l->row1().setData(r1);
l->row2().setData(r2);
l->row1().setData(r1);
l->row2().setData(r2);
bool b1 = l->row1().isNullValue(fSpec.fIndex);
bool b2 = l->row2().isNullValue(fSpec.fIndex);
bool b1 = l->row1().isNullValue(fSpec.fIndex);
bool b2 = l->row2().isNullValue(fSpec.fIndex);
int ret = 0;
int ret = 0;
if (b1 == true || b2 == true)
{
if (b1 == false && b2 == true)
ret = fSpec.fNf;
else if (b1 == true && b2 == false)
ret = -fSpec.fNf;
}
else
{
double v1 = l->row1().getDoubleField(fSpec.fIndex);
double v2 = l->row2().getDoubleField(fSpec.fIndex);
if (b1 == true || b2 == true)
{
if (b1 == false && b2 == true)
ret = fSpec.fNf;
else if (b1 == true && b2 == false)
ret = -fSpec.fNf;
}
else
{
double v1 = l->row1().getDoubleField(fSpec.fIndex);
double v2 = l->row2().getDoubleField(fSpec.fIndex);
if (v1 > v2)
ret = fSpec.fAsc;
else if (v1 < v2)
ret = -fSpec.fAsc;
}
if (v1 > v2)
ret = fSpec.fAsc;
else if (v1 < v2)
ret = -fSpec.fAsc;
}
return ret;
return ret;
}
int FloatCompare::operator()(IdbCompare* l, Row::Pointer r1, Row::Pointer r2)
{
l->row1().setData(r1);
l->row2().setData(r2);
l->row1().setData(r1);
l->row2().setData(r2);
bool b1 = l->row1().isNullValue(fSpec.fIndex);
bool b2 = l->row2().isNullValue(fSpec.fIndex);
bool b1 = l->row1().isNullValue(fSpec.fIndex);
bool b2 = l->row2().isNullValue(fSpec.fIndex);
int ret = 0;
int ret = 0;
if (b1 == true || b2 == true)
{
if (b1 == false && b2 == true)
ret = fSpec.fNf;
else if (b1 == true && b2 == false)
ret = -fSpec.fNf;
}
else
{
float v1 = l->row1().getFloatField(fSpec.fIndex);
float v2 = l->row2().getFloatField(fSpec.fIndex);
if (b1 == true || b2 == true)
{
if (b1 == false && b2 == true)
ret = fSpec.fNf;
else if (b1 == true && b2 == false)
ret = -fSpec.fNf;
}
else
{
float v1 = l->row1().getFloatField(fSpec.fIndex);
float v2 = l->row2().getFloatField(fSpec.fIndex);
if (v1 > v2)
ret = fSpec.fAsc;
else if (v1 < v2)
ret = -fSpec.fAsc;
}
if (v1 > v2)
ret = fSpec.fAsc;
else if (v1 < v2)
ret = -fSpec.fAsc;
}
return ret;
return ret;
}
bool CompareRule::less(Row::Pointer r1, Row::Pointer r2)
{
for (vector<Compare*>::iterator i = fCompares.begin(); i != fCompares.end(); i++)
{
int c = ((*(*i))(fIdbCompare, r1, r2));
for (vector<Compare*>::iterator i = fCompares.begin(); i != fCompares.end(); i++)
{
int c = ((*(*i))(fIdbCompare, r1, r2));
if (c < 0)
return true;
else if (c > 0)
return false;
}
if (c < 0)
return true;
else if (c > 0)
return false;
}
return false;
return false;
}
void CompareRule::compileRules(const std::vector<IdbSortSpec>& spec, const rowgroup::RowGroup& rg)
{
const vector<CalpontSystemCatalog::ColDataType>& types = rg.getColTypes();
for (vector<IdbSortSpec>::const_iterator i = spec.begin(); i != spec.end(); i++)
{
switch (types[i->fIndex])
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
const vector<CalpontSystemCatalog::ColDataType>& types = rg.getColTypes();
for (vector<IdbSortSpec>::const_iterator i = spec.begin(); i != spec.end(); i++)
{
switch (types[i->fIndex])
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
case CalpontSystemCatalog::UDECIMAL:
{
Compare* c = new IntCompare(*i);
fCompares.push_back(c);
break;
}
{
Compare* c = new IntCompare(*i);
fCompares.push_back(c);
break;
}
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
@ -252,212 +254,226 @@ void CompareRule::compileRules(const std::vector<IdbSortSpec>& spec, const rowgr
fCompares.push_back(c);
break;
}
case CalpontSystemCatalog::CHAR:
case CalpontSystemCatalog::VARCHAR:
{
Compare* c = new StringCompare(*i);
fCompares.push_back(c);
break;
}
case CalpontSystemCatalog::CHAR:
case CalpontSystemCatalog::VARCHAR:
{
Compare* c = new StringCompare(*i);
fCompares.push_back(c);
break;
}
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
{
Compare* c = new DoubleCompare(*i);
fCompares.push_back(c);
break;
}
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UDOUBLE:
{
Compare* c = new DoubleCompare(*i);
fCompares.push_back(c);
break;
}
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
{
Compare* c = new FloatCompare(*i);
fCompares.push_back(c);
break;
}
case CalpontSystemCatalog::DATE:
case CalpontSystemCatalog::DATETIME:
{
Compare* c = new UintCompare(*i);
fCompares.push_back(c);
break;
}
default:
{
break;
}
}
}
{
Compare* c = new FloatCompare(*i);
fCompares.push_back(c);
break;
}
case CalpontSystemCatalog::DATE:
case CalpontSystemCatalog::DATETIME:
{
Compare* c = new UintCompare(*i);
fCompares.push_back(c);
break;
}
default:
{
break;
}
}
}
}
void IdbCompare::initialize(const RowGroup& rg)
{
fRowGroup = rg;
fRowGroup.initRow(&fRow1);
fRowGroup.initRow(&fRow2);
fRowGroup = rg;
fRowGroup.initRow(&fRow1);
fRowGroup.initRow(&fRow2);
}
void IdbCompare::setStringTable(bool b)
{
fRowGroup.setUseStringTable(b);
fRowGroup.initRow(&fRow1);
fRowGroup.initRow(&fRow2);
fRowGroup.setUseStringTable(b);
fRowGroup.initRow(&fRow1);
fRowGroup.initRow(&fRow2);
}
// OrderByData class implementation
OrderByData::OrderByData(const std::vector<IdbSortSpec>& spec, const rowgroup::RowGroup& rg)
{
IdbCompare::initialize(rg);
fRule.compileRules(spec, rg);
fRule.fIdbCompare = this;
IdbCompare::initialize(rg);
fRule.compileRules(spec, rg);
fRule.fIdbCompare = this;
}
// IdbOrderBy class implementation
IdbOrderBy::IdbOrderBy() :
fDistinct(false), fMemSize(0), fRowsPerRG(8192), fErrorCode(0), fRm(NULL)
fDistinct(false), fMemSize(0), fRowsPerRG(8192), fErrorCode(0), fRm(NULL)
{
}
IdbOrderBy::~IdbOrderBy()
{
if (fRm)
fRm->returnMemory(fMemSize, fSessionMemLimit);
if (fRm)
fRm->returnMemory(fMemSize, fSessionMemLimit);
// delete compare objects
vector<Compare*>::iterator i = fRule.fCompares.begin();
while (i != fRule.fCompares.end())
delete *i++;
// delete compare objects
vector<Compare*>::iterator i = fRule.fCompares.begin();
while (i != fRule.fCompares.end())
delete *i++;
}
void IdbOrderBy::initialize(const RowGroup& rg)
{
// initialize rows
IdbCompare::initialize(rg);
// initialize rows
IdbCompare::initialize(rg);
uint64_t newSize = fRowsPerRG * rg.getRowSize();
fMemSize += newSize;
uint64_t newSize = fRowsPerRG * rg.getRowSize();
fMemSize += newSize;
if (!fRm->getMemory(newSize, fSessionMemLimit))
{
cerr << IDBErrorInfo::instance()->errorMsg(fErrorCode)
<< " @" << __FILE__ << ":" << __LINE__;
throw IDBExcept(fErrorCode);
}
fData.reinit(fRowGroup, fRowsPerRG);
fRowGroup.setData(&fData);
fRowGroup.resetRowGroup(0);
fRowGroup.initRow(&fRow0);
fRowGroup.getRow(0, &fRow0);
{
cerr << IDBErrorInfo::instance()->errorMsg(fErrorCode)
<< " @" << __FILE__ << ":" << __LINE__;
throw IDBExcept(fErrorCode);
}
// set compare functors
fRule.compileRules(fOrderByCond, fRowGroup);
fData.reinit(fRowGroup, fRowsPerRG);
fRowGroup.setData(&fData);
fRowGroup.resetRowGroup(0);
fRowGroup.initRow(&fRow0);
fRowGroup.getRow(0, &fRow0);
fRowGroup.initRow(&row1);
fRowGroup.initRow(&row2);
if (fDistinct)
{
fDistinctMap.reset(new DistinctMap_t(10, Hasher(this, getKeyLength()), Eq(this, getKeyLength())));
}
// set compare functors
fRule.compileRules(fOrderByCond, fRowGroup);
fRowGroup.initRow(&row1);
fRowGroup.initRow(&row2);
if (fDistinct)
{
fDistinctMap.reset(new DistinctMap_t(10, Hasher(this, getKeyLength()), Eq(this, getKeyLength())));
}
}
bool IdbOrderBy::getData(RGData& data)
{
if (fDataQueue.empty())
return false;
if (fDataQueue.empty())
return false;
data = fDataQueue.front();
fDataQueue.pop();
data = fDataQueue.front();
fDataQueue.pop();
return true;
return true;
}
bool EqualCompData::operator()(Row::Pointer a, Row::Pointer b)
{
bool eq = true;
fRow1.setData(a);
fRow2.setData(b);
bool eq = true;
fRow1.setData(a);
fRow2.setData(b);
for (vector<uint64_t>::const_iterator i = fIndex.begin(); i != fIndex.end() && eq; i++)
{
CalpontSystemCatalog::ColDataType type = fRow1.getColType(*i);
switch (type)
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
for (vector<uint64_t>::const_iterator i = fIndex.begin(); i != fIndex.end() && eq; i++)
{
CalpontSystemCatalog::ColDataType type = fRow1.getColType(*i);
switch (type)
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
case CalpontSystemCatalog::UDECIMAL:
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::DATE:
case CalpontSystemCatalog::DATETIME:
case CalpontSystemCatalog::DATE:
case CalpontSystemCatalog::DATETIME:
{
// equal compare. ignore sign and null
eq = (fRow1.getUintField(*i) == fRow2.getUintField(*i));
// equal compare. ignore sign and null
eq = (fRow1.getUintField(*i) == fRow2.getUintField(*i));
break;
}
case CalpontSystemCatalog::CHAR:
case CalpontSystemCatalog::VARCHAR:
{
eq = (fRow1.getStringField(*i) == fRow2.getStringField(*i));
break;
}
case CalpontSystemCatalog::CHAR:
case CalpontSystemCatalog::VARCHAR:
{
eq = (fRow1.getStringField(*i) == fRow2.getStringField(*i));
break;
}
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
{
eq = (fRow1.getDoubleField(*i) == fRow2.getDoubleField(*i));
break;
}
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UDOUBLE:
{
eq = (fRow1.getDoubleField(*i) == fRow2.getDoubleField(*i));
break;
}
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
{
eq = (fRow1.getFloatField(*i) == fRow2.getFloatField(*i));
break;
}
default:
{
eq = false;
uint64_t ec = ERR_WF_UNKNOWN_COL_TYPE;
cerr << IDBErrorInfo::instance()->errorMsg(ec, type)
<< " @" << __FILE__ << ":" << __LINE__;
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ec, type), ec);
break;
}
}
}
{
eq = (fRow1.getFloatField(*i) == fRow2.getFloatField(*i));
break;
}
return eq;
default:
{
eq = false;
uint64_t ec = ERR_WF_UNKNOWN_COL_TYPE;
cerr << IDBErrorInfo::instance()->errorMsg(ec, type)
<< " @" << __FILE__ << ":" << __LINE__;
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ec, type), ec);
break;
}
}
}
return eq;
}
uint64_t IdbOrderBy::Hasher::operator()(const Row::Pointer &p) const
uint64_t IdbOrderBy::Hasher::operator()(const Row::Pointer& p) const
{
Row &row = ts->row1;
row.setPointer(p);
uint64_t ret = row.hash(colCount);
//cout << "hash(): returning " << ret << " for row: " << row.toString() << endl;
return ret;
Row& row = ts->row1;
row.setPointer(p);
uint64_t ret = row.hash(colCount);
//cout << "hash(): returning " << ret << " for row: " << row.toString() << endl;
return ret;
}
bool IdbOrderBy::Eq::operator()(const Row::Pointer &d1, const Row::Pointer &d2) const
bool IdbOrderBy::Eq::operator()(const Row::Pointer& d1, const Row::Pointer& d2) const
{
Row &r1 = ts->row1, &r2 = ts->row2;
r1.setPointer(d1);
r2.setPointer(d2);
bool ret = r1.equals(r2, colCount);
//cout << "equals(): returning " << (int) ret << " for r1: " << r1.toString() << " r2: " << r2.toString()
// << endl;
Row& r1 = ts->row1, &r2 = ts->row2;
r1.setPointer(d1);
r2.setPointer(d2);
bool ret = r1.equals(r2, colCount);
//cout << "equals(): returning " << (int) ret << " for r1: " << r1.toString() << " r2: " << r2.toString()
// << endl;
return ret;
return ret;
}

View File

@ -58,13 +58,13 @@ class IdbCompare;
// order by specification
struct IdbSortSpec
{
int fIndex;
int fAsc; // <ordering specification> ::= ASC | DESC
int fNf; // <null ordering> ::= NULLS FIRST | NULLS LAST
int fIndex;
int fAsc; // <ordering specification> ::= ASC | DESC
int fNf; // <null ordering> ::= NULLS FIRST | NULLS LAST
IdbSortSpec() : fIndex(-1), fAsc(1), fNf(1) {}
IdbSortSpec(int i, bool b) : fIndex(i), fAsc(b ? 1 : -1), fNf(fAsc) {}
IdbSortSpec(int i, bool b, bool n) : fIndex(i), fAsc(b ? 1 : -1), fNf(n ? 1 : -1) {}
IdbSortSpec() : fIndex(-1), fAsc(1), fNf(1) {}
IdbSortSpec(int i, bool b) : fIndex(i), fAsc(b ? 1 : -1), fNf(fAsc) {}
IdbSortSpec(int i, bool b, bool n) : fIndex(i), fAsc(b ? 1 : -1), fNf(n ? 1 : -1) {}
};
@ -73,134 +73,152 @@ struct IdbSortSpec
class Compare
{
public:
Compare(const IdbSortSpec& spec) : fSpec(spec) {}
virtual ~Compare() {}
Compare(const IdbSortSpec& spec) : fSpec(spec) {}
virtual ~Compare() {}
virtual int operator()(IdbCompare*, rowgroup::Row::Pointer, rowgroup::Row::Pointer) = 0;
virtual int operator()(IdbCompare*, rowgroup::Row::Pointer, rowgroup::Row::Pointer) = 0;
protected:
IdbSortSpec fSpec;
IdbSortSpec fSpec;
};
class IntCompare : public Compare
{
public:
IntCompare(const IdbSortSpec& spec) : Compare(spec) {}
IntCompare(const IdbSortSpec& spec) : Compare(spec) {}
int operator()(IdbCompare*, rowgroup::Row::Pointer, rowgroup::Row::Pointer);
int operator()(IdbCompare*, rowgroup::Row::Pointer, rowgroup::Row::Pointer);
};
class UintCompare : public Compare
{
public:
UintCompare(const IdbSortSpec& spec) : Compare(spec) {}
UintCompare(const IdbSortSpec& spec) : Compare(spec) {}
int operator()(IdbCompare*, rowgroup::Row::Pointer, rowgroup::Row::Pointer);
int operator()(IdbCompare*, rowgroup::Row::Pointer, rowgroup::Row::Pointer);
};
class StringCompare : public Compare
{
public:
StringCompare(const IdbSortSpec& spec) : Compare(spec) {}
StringCompare(const IdbSortSpec& spec) : Compare(spec) {}
int operator()(IdbCompare*, rowgroup::Row::Pointer, rowgroup::Row::Pointer);
int operator()(IdbCompare*, rowgroup::Row::Pointer, rowgroup::Row::Pointer);
};
class DoubleCompare : public Compare
{
public:
DoubleCompare(const IdbSortSpec& spec) : Compare(spec) {}
DoubleCompare(const IdbSortSpec& spec) : Compare(spec) {}
int operator()(IdbCompare*, rowgroup::Row::Pointer, rowgroup::Row::Pointer);
int operator()(IdbCompare*, rowgroup::Row::Pointer, rowgroup::Row::Pointer);
};
class FloatCompare : public Compare
{
public:
FloatCompare(const IdbSortSpec& spec) : Compare(spec) {}
FloatCompare(const IdbSortSpec& spec) : Compare(spec) {}
int operator()(IdbCompare*, rowgroup::Row::Pointer, rowgroup::Row::Pointer);
int operator()(IdbCompare*, rowgroup::Row::Pointer, rowgroup::Row::Pointer);
};
class CompareRule
{
public:
CompareRule(IdbCompare* c = NULL) : fIdbCompare(c) {}
CompareRule(IdbCompare* c = NULL) : fIdbCompare(c) {}
bool less(rowgroup::Row::Pointer r1, rowgroup::Row::Pointer r2);
bool less(rowgroup::Row::Pointer r1, rowgroup::Row::Pointer r2);
void compileRules(const std::vector<IdbSortSpec>&, const rowgroup::RowGroup&);
void compileRules(const std::vector<IdbSortSpec>&, const rowgroup::RowGroup&);
std::vector<Compare*> fCompares;
IdbCompare* fIdbCompare;
std::vector<Compare*> fCompares;
IdbCompare* fIdbCompare;
};
class IdbCompare
{
public:
IdbCompare() {};
virtual ~IdbCompare() {};
IdbCompare() {};
virtual ~IdbCompare() {};
virtual void initialize(const rowgroup::RowGroup&);
void setStringTable(bool b);
virtual void initialize(const rowgroup::RowGroup&);
void setStringTable(bool b);
rowgroup::Row& row1() { return fRow1; }
rowgroup::Row& row2() { return fRow2; }
rowgroup::Row& row1()
{
return fRow1;
}
rowgroup::Row& row2()
{
return fRow2;
}
protected:
rowgroup::RowGroup fRowGroup;
rowgroup::Row fRow1;
rowgroup::Row fRow2;
rowgroup::RowGroup fRowGroup;
rowgroup::Row fRow1;
rowgroup::Row fRow2;
};
class OrderByRow
{
public:
OrderByRow(const rowgroup::Row& r, CompareRule& c) : fData(r.getPointer()), fRule(&c) {}
OrderByRow(const rowgroup::Row& r, CompareRule& c) : fData(r.getPointer()), fRule(&c) {}
bool operator < (const OrderByRow& rhs) const { return fRule->less(fData, rhs.fData); }
bool operator < (const OrderByRow& rhs) const
{
return fRule->less(fData, rhs.fData);
}
rowgroup::Row::Pointer fData;
CompareRule* fRule;
rowgroup::Row::Pointer fData;
CompareRule* fRule;
};
class EqualCompData : public IdbCompare
{
public:
EqualCompData(std::vector<uint64_t>& v) : fIndex(v) {}
EqualCompData(std::vector<uint64_t>& v, const rowgroup::RowGroup& rg) :
fIndex(v) { initialize(rg); }
EqualCompData(std::vector<uint64_t>& v) : fIndex(v) {}
EqualCompData(std::vector<uint64_t>& v, const rowgroup::RowGroup& rg) :
fIndex(v)
{
initialize(rg);
}
~EqualCompData() {};
~EqualCompData() {};
bool operator()(rowgroup::Row::Pointer, rowgroup::Row::Pointer);
bool operator()(rowgroup::Row::Pointer, rowgroup::Row::Pointer);
//protected:
std::vector<uint64_t> fIndex;
std::vector<uint64_t> fIndex;
};
class OrderByData : public IdbCompare
{
public:
OrderByData(const std::vector<IdbSortSpec>&, const rowgroup::RowGroup&);
virtual ~OrderByData() {};
OrderByData(const std::vector<IdbSortSpec>&, const rowgroup::RowGroup&);
virtual ~OrderByData() {};
bool operator() (rowgroup::Row::Pointer p1, rowgroup::Row::Pointer p2) { return fRule.less(p1, p2); }
const CompareRule& rule() const { return fRule; }
bool operator() (rowgroup::Row::Pointer p1, rowgroup::Row::Pointer p2)
{
return fRule.less(p1, p2);
}
const CompareRule& rule() const
{
return fRule;
}
protected:
CompareRule fRule;
CompareRule fRule;
};
@ -208,53 +226,61 @@ protected:
class IdbOrderBy : public IdbCompare
{
public:
IdbOrderBy();
virtual ~IdbOrderBy();
IdbOrderBy();
virtual ~IdbOrderBy();
virtual void initialize(const rowgroup::RowGroup&);
virtual void processRow(const rowgroup::Row&) = 0;
virtual uint64_t getKeyLength() const = 0;
virtual const std::string toString() const = 0;
virtual void initialize(const rowgroup::RowGroup&);
virtual void processRow(const rowgroup::Row&) = 0;
virtual uint64_t getKeyLength() const = 0;
virtual const std::string toString() const = 0;
bool getData(rowgroup::RGData& data);
bool getData(rowgroup::RGData& data);
void distinct(bool b) { fDistinct = b; }
bool distinct() const { return fDistinct; }
void distinct(bool b)
{
fDistinct = b;
}
bool distinct() const
{
return fDistinct;
}
protected:
std::vector<IdbSortSpec> fOrderByCond;
std::priority_queue<OrderByRow> fOrderByQueue;
rowgroup::Row fRow0;
CompareRule fRule;
std::vector<IdbSortSpec> fOrderByCond;
std::priority_queue<OrderByRow> fOrderByQueue;
rowgroup::Row fRow0;
CompareRule fRule;
rowgroup::RGData fData;
std::queue<rowgroup::RGData> fDataQueue;
rowgroup::RGData fData;
std::queue<rowgroup::RGData> fDataQueue;
struct Hasher {
IdbOrderBy *ts;
utils::Hasher_r h;
uint32_t colCount;
Hasher(IdbOrderBy *t, uint32_t c) : ts(t), colCount(c) { }
uint64_t operator()(const rowgroup::Row::Pointer &) const;
};
struct Eq {
IdbOrderBy *ts;
uint32_t colCount;
Eq(IdbOrderBy *t, uint32_t c) : ts(t), colCount(c) { }
bool operator()(const rowgroup::Row::Pointer &, const rowgroup::Row::Pointer &) const;
};
struct Hasher
{
IdbOrderBy* ts;
utils::Hasher_r h;
uint32_t colCount;
Hasher(IdbOrderBy* t, uint32_t c) : ts(t), colCount(c) { }
uint64_t operator()(const rowgroup::Row::Pointer&) const;
};
struct Eq
{
IdbOrderBy* ts;
uint32_t colCount;
Eq(IdbOrderBy* t, uint32_t c) : ts(t), colCount(c) { }
bool operator()(const rowgroup::Row::Pointer&, const rowgroup::Row::Pointer&) const;
};
typedef std::tr1::unordered_set<rowgroup::Row::Pointer, Hasher, Eq,
utils::STLPoolAllocator<rowgroup::Row::Pointer> > DistinctMap_t;
boost::scoped_ptr<DistinctMap_t> fDistinctMap;
rowgroup::Row row1, row2; // scratch space for Hasher & Eq
typedef std::tr1::unordered_set<rowgroup::Row::Pointer, Hasher, Eq,
utils::STLPoolAllocator<rowgroup::Row::Pointer> > DistinctMap_t;
boost::scoped_ptr<DistinctMap_t> fDistinctMap;
rowgroup::Row row1, row2; // scratch space for Hasher & Eq
bool fDistinct;
uint64_t fMemSize;
uint64_t fRowsPerRG;
uint64_t fErrorCode;
joblist::ResourceManager* fRm;
boost::shared_ptr<int64_t> fSessionMemLimit;
bool fDistinct;
uint64_t fMemSize;
uint64_t fRowsPerRG;
uint64_t fErrorCode;
joblist::ResourceManager* fRm;
boost::shared_ptr<int64_t> fSessionMemLimit;
};

View File

@ -56,96 +56,101 @@ namespace windowfunction
template<typename T>
boost::shared_ptr<WindowFunctionType> WF_count<T>::makeFunction(int id, const string& name, int ct)
{
boost::shared_ptr<WindowFunctionType> func;
switch (ct)
{
case CalpontSystemCatalog::CHAR:
case CalpontSystemCatalog::VARCHAR:
case CalpontSystemCatalog::VARBINARY:
{
func.reset(new WF_count<string>(id, name));
break;
}
default:
{
func.reset(new WF_count<int64_t>(id, name));
break;
}
}
boost::shared_ptr<WindowFunctionType> func;
return func;
switch (ct)
{
case CalpontSystemCatalog::CHAR:
case CalpontSystemCatalog::VARCHAR:
case CalpontSystemCatalog::VARBINARY:
{
func.reset(new WF_count<string>(id, name));
break;
}
default:
{
func.reset(new WF_count<int64_t>(id, name));
break;
}
}
return func;
}
template<typename T>
WindowFunctionType* WF_count<T>::clone() const
{
return new WF_count(*this);
return new WF_count(*this);
}
template<typename T>
void WF_count<T>::resetData()
{
fCount = 0;
fSet.clear();
fCount = 0;
fSet.clear();
WindowFunctionType::resetData();
WindowFunctionType::resetData();
}
template<typename T>
void WF_count<T>::operator()(int64_t b, int64_t e, int64_t c)
{
if ((fFrameUnit == WF__FRAME_ROWS) ||
(fPrev == -1) ||
(!fPeer->operator()(getPointer(fRowData->at(c)), getPointer(fRowData->at(fPrev)))))
{
// for unbounded - current row special handling
if (fPrev >= b && fPrev < c)
b = c;
else if (fPrev <= e && fPrev > c)
e = c;
if ((fFrameUnit == WF__FRAME_ROWS) ||
(fPrev == -1) ||
(!fPeer->operator()(getPointer(fRowData->at(c)), getPointer(fRowData->at(fPrev)))))
{
// for unbounded - current row special handling
if (fPrev >= b && fPrev < c)
b = c;
else if (fPrev <= e && fPrev > c)
e = c;
// for count(*), the column is optimized out, index[1] does not exist.
uint64_t colIn = (fFunctionId == WF__COUNT_ASTERISK) ? 0 : fFieldIndex[1];
for (int64_t i = b; i <= e; i++)
{
if (i % 1000 == 0 && fStep->cancelled())
break;
// for count(*), the column is optimized out, index[1] does not exist.
uint64_t colIn = (fFunctionId == WF__COUNT_ASTERISK) ? 0 : fFieldIndex[1];
if (fFunctionId == WF__COUNT_ASTERISK)
{
fCount++;
continue;
}
for (int64_t i = b; i <= e; i++)
{
if (i % 1000 == 0 && fStep->cancelled())
break;
fRow.setData(getPointer(fRowData->at(i)));
if (fRow.isNullValue(colIn) == true)
continue;
if (fFunctionId == WF__COUNT_ASTERISK)
{
fCount++;
continue;
}
if (fFunctionId != WF__COUNT_DISTINCT)
{
fCount++;
}
else
{
T valIn;
getValue(colIn, valIn);
if (fSet.find(valIn) == fSet.end())
{
fCount++;
fRow.setData(getPointer(fRowData->at(i)));
if (fFunctionId == WF__COUNT_DISTINCT)
fSet.insert(valIn);
}
}
}
}
if (fRow.isNullValue(colIn) == true)
continue;
setValue(CalpontSystemCatalog::BIGINT, b, e, c, &fCount);
if (fFunctionId != WF__COUNT_DISTINCT)
{
fCount++;
}
else
{
T valIn;
getValue(colIn, valIn);
fPrev = c;
if (fSet.find(valIn) == fSet.end())
{
fCount++;
if (fFunctionId == WF__COUNT_DISTINCT)
fSet.insert(valIn);
}
}
}
}
setValue(CalpontSystemCatalog::BIGINT, b, e, c, &fCount);
fPrev = c;
}

View File

@ -33,19 +33,22 @@ template<typename T>
class WF_count : public WindowFunctionType
{
public:
WF_count(int id, const std::string& name) : WindowFunctionType(id, name) {resetData();}
WF_count(int id, const std::string& name) : WindowFunctionType(id, name)
{
resetData();
}
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
static boost::shared_ptr<WindowFunctionType> makeFunction(int, const string&, int);
static boost::shared_ptr<WindowFunctionType> makeFunction(int, const string&, int);
protected:
uint64_t fCount;
std::set<T> fSet;
uint64_t fCount;
std::set<T> fSet;
};

View File

@ -54,213 +54,232 @@ namespace windowfunction
template<typename T>
boost::shared_ptr<WindowFunctionType> WF_lead_lag<T>::makeFunction(int id, const string& name, int ct)
{
boost::shared_ptr<WindowFunctionType> func;
switch (ct)
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
{
func.reset(new WF_lead_lag<int64_t>(id, name));
break;
}
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UDECIMAL:
case CalpontSystemCatalog::DATE:
case CalpontSystemCatalog::DATETIME:
{
func.reset(new WF_lead_lag<uint64_t>(id, name));
break;
}
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
{
func.reset(new WF_lead_lag<double>(id, name));
break;
}
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
{
func.reset(new WF_lead_lag<float>(id, name));
break;
}
default:
{
func.reset(new WF_lead_lag<string>(id, name));
break;
}
}
boost::shared_ptr<WindowFunctionType> func;
return func;
switch (ct)
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
{
func.reset(new WF_lead_lag<int64_t>(id, name));
break;
}
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UDECIMAL:
case CalpontSystemCatalog::DATE:
case CalpontSystemCatalog::DATETIME:
{
func.reset(new WF_lead_lag<uint64_t>(id, name));
break;
}
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
{
func.reset(new WF_lead_lag<double>(id, name));
break;
}
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
{
func.reset(new WF_lead_lag<float>(id, name));
break;
}
default:
{
func.reset(new WF_lead_lag<string>(id, name));
break;
}
}
return func;
}
template<typename T>
WindowFunctionType* WF_lead_lag<T>::clone() const
{
return new WF_lead_lag<T>(*this);
return new WF_lead_lag<T>(*this);
}
template<typename T>
void WF_lead_lag<T>::resetData()
{
WindowFunctionType::resetData();
WindowFunctionType::resetData();
}
template<typename T>
void WF_lead_lag<T>::parseParms(const std::vector<execplan::SRCP>& parms)
{
// lead | lag
fLead = 1;
// lead | lag
fLead = 1;
fRespectNulls = true;
fDefNull = false;
fDefault = (T)0;
fOffsetNull = false;
fOffset = 0;
if (fFunctionId == WF__LAG)
fLead = -1;
// parms[0]: value-expr
// skip
if (fFunctionId == WF__LAG)
fLead = -1;
// parms[1]: offset
ConstantColumn* cc = dynamic_cast<ConstantColumn*>(parms[1].get());
if (cc != NULL)
{
fOffsetNull = false;
fOffset = cc->getIntVal(fRow, fOffsetNull) * fLead; // row not used, no need to setData.
}
// parms[0]: value-expr
// skip
// parms[2]: default value
cc = dynamic_cast<ConstantColumn*>(parms[2].get());
if (cc != NULL)
{
fDefNull = false;
getConstValue(cc, fDefault, fDefNull);
}
// parms[1]: offset
ConstantColumn* cc = dynamic_cast<ConstantColumn*>(parms[1].get());
// parms[3]: respect null | ignore null
cc = dynamic_cast<ConstantColumn*>(parms[3].get());
idbassert(cc != NULL);
bool isNull = false; // dummy, harded coded
fRespectNulls = (cc->getIntVal(fRow, isNull) > 0);
if (cc != NULL)
{
fOffsetNull = false;
fOffset = cc->getIntVal(fRow, fOffsetNull) * fLead; // row not used, no need to setData.
}
// parms[2]: default value
cc = dynamic_cast<ConstantColumn*>(parms[2].get());
if (cc != NULL)
{
fDefNull = false;
getConstValue(cc, fDefault, fDefNull);
}
// parms[3]: respect null | ignore null
cc = dynamic_cast<ConstantColumn*>(parms[3].get());
idbassert(cc != NULL);
bool isNull = false; // dummy, harded coded
fRespectNulls = (cc->getIntVal(fRow, isNull) > 0);
}
template<typename T>
void WF_lead_lag<T>::operator()(int64_t b, int64_t e, int64_t c)
{
uint64_t colIn = fFieldIndex[1];
bool isNull = true;
for (int64_t c = b; c <= e; c++)
{
if (c % 1000 == 0 && fStep->cancelled())
break;
uint64_t colIn = fFieldIndex[1];
bool isNull = true;
fRow.setData(getPointer(fRowData->at(c)));
// get offset if not constant
int64_t idx = fFieldIndex[2];
if (idx != -1)
{
double tmp = 0.0; // use double to cover all column types
fOffsetNull = fRow.isNullValue(idx);
if (!fOffsetNull)
{
implicit2T(idx, tmp, 0);
for (int64_t c = b; c <= e; c++)
{
if (c % 1000 == 0 && fStep->cancelled())
break;
if (tmp > e) // prevent integer overflow
tmp = e + 1;
else if (tmp + e < 0)
tmp += e - 1;
fRow.setData(getPointer(fRowData->at(c)));
// get offset if not constant
int64_t idx = fFieldIndex[2];
fOffset = (int64_t) tmp;
fOffset *= fLead;
}
}
if (idx != -1)
{
double tmp = 0.0; // use double to cover all column types
fOffsetNull = fRow.isNullValue(idx);
// get default if not constant
idx = fFieldIndex[3];
if (idx != -1)
{
fDefNull = fRow.isNullValue(idx);
if (!fDefNull)
implicit2T(idx, fDefault, (int) fRow.getScale(idx));
}
if (!fOffsetNull)
{
implicit2T(idx, tmp, 0);
int64_t o = c + fOffset;
if (o < b || o > e || fOffsetNull) // out of bound
{
T* v = (fDefNull) ? NULL : &fDefault;
setValue(fRow.getColType(fFieldIndex[0]), b, e, c, v);
continue;
}
if (tmp > e) // prevent integer overflow
tmp = e + 1;
else if (tmp + e < 0)
tmp += e - 1;
if (fRespectNulls == false && fRow.isNullValue(colIn) == true)
{
if(fOffset > 0)
{
while (++o < e)
{
fRow.setData(getPointer(fRowData->at(o)));
if (fRow.isNullValue(colIn) == false)
break;
}
fOffset = (int64_t) tmp;
fOffset *= fLead;
}
}
if (o <= e)
{
fRow.setData(getPointer(fRowData->at(o)));
getValue(colIn, fValue);
isNull = fRow.isNullValue(colIn);
}
}
else if (fOffset < 0)
{
while (--o > b)
{
fRow.setData(getPointer(fRowData->at(o)));
if (fRow.isNullValue(colIn) == false)
break;
}
// get default if not constant
idx = fFieldIndex[3];
if (o >= b)
{
fRow.setData(getPointer(fRowData->at(o)));
getValue(colIn, fValue);
isNull = fRow.isNullValue(colIn);
}
}
if (idx != -1)
{
fDefNull = fRow.isNullValue(idx);
T* v = NULL;
if (!isNull)
v = &fValue;
else if (!fDefNull)
v = &fDefault;
if (!fDefNull)
implicit2T(idx, fDefault, (int) fRow.getScale(idx));
}
setValue(fRow.getColType(fFieldIndex[0]), b, e, c, v);
}
else
{
fRow.setData(getPointer(fRowData->at(o)));
getValue(colIn, fValue);
isNull = fRow.isNullValue(colIn);
int64_t o = c + fOffset;
T* v = NULL;
if (!isNull)
v = &fValue;
else if (!fDefNull)
v = &fDefault;
setValue(fRow.getColType(fFieldIndex[0]), b, e, c, v);
}
}
if (o < b || o > e || fOffsetNull) // out of bound
{
T* v = (fDefNull) ? NULL : &fDefault;
setValue(fRow.getColType(fFieldIndex[0]), b, e, c, v);
continue;
}
if (fRespectNulls == false && fRow.isNullValue(colIn) == true)
{
if (fOffset > 0)
{
while (++o < e)
{
fRow.setData(getPointer(fRowData->at(o)));
if (fRow.isNullValue(colIn) == false)
break;
}
if (o <= e)
{
fRow.setData(getPointer(fRowData->at(o)));
getValue(colIn, fValue);
isNull = fRow.isNullValue(colIn);
}
}
else if (fOffset < 0)
{
while (--o > b)
{
fRow.setData(getPointer(fRowData->at(o)));
if (fRow.isNullValue(colIn) == false)
break;
}
if (o >= b)
{
fRow.setData(getPointer(fRowData->at(o)));
getValue(colIn, fValue);
isNull = fRow.isNullValue(colIn);
}
}
T* v = NULL;
if (!isNull)
v = &fValue;
else if (!fDefNull)
v = &fDefault;
setValue(fRow.getColType(fFieldIndex[0]), b, e, c, v);
}
else
{
fRow.setData(getPointer(fRowData->at(o)));
getValue(colIn, fValue);
isNull = fRow.isNullValue(colIn);
T* v = NULL;
if (!isNull)
v = &fValue;
else if (!fDefNull)
v = &fDefault;
setValue(fRow.getColType(fFieldIndex[0]), b, e, c, v);
}
}
}

View File

@ -32,24 +32,27 @@ template<typename T>
class WF_lead_lag : public WindowFunctionType
{
public:
WF_lead_lag(int id, const std::string& name) : WindowFunctionType(id, name) {resetData();}
WF_lead_lag(int id, const std::string& name) : WindowFunctionType(id, name)
{
resetData();
}
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
void parseParms(const std::vector<execplan::SRCP>&);
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
void parseParms(const std::vector<execplan::SRCP>&);
static boost::shared_ptr<WindowFunctionType> makeFunction(int, const string&, int);
static boost::shared_ptr<WindowFunctionType> makeFunction(int, const string&, int);
protected:
T fValue;
T fDefault;
int64_t fOffset;
int64_t fLead;
bool fOffsetNull;
bool fDefNull;
bool fRespectNulls; // respect null | ignore null
T fValue;
T fDefault;
int64_t fOffset;
int64_t fLead;
bool fOffsetNull;
bool fDefNull;
bool fRespectNulls; // respect null | ignore null
};

View File

@ -53,105 +53,113 @@ namespace windowfunction
template<typename T>
boost::shared_ptr<WindowFunctionType> WF_min_max<T>::makeFunction(int id, const string& name, int ct)
{
boost::shared_ptr<WindowFunctionType> func;
switch (ct)
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
{
func.reset(new WF_min_max<int64_t>(id, name));
break;
}
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UDECIMAL:
case CalpontSystemCatalog::DATE:
case CalpontSystemCatalog::DATETIME:
{
func.reset(new WF_min_max<uint64_t>(id, name));
break;
}
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
{
func.reset(new WF_min_max<double>(id, name));
break;
}
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
{
func.reset(new WF_min_max<float>(id, name));
break;
}
default:
{
func.reset(new WF_min_max<string>(id, name));
break;
}
}
boost::shared_ptr<WindowFunctionType> func;
return func;
switch (ct)
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
{
func.reset(new WF_min_max<int64_t>(id, name));
break;
}
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UDECIMAL:
case CalpontSystemCatalog::DATE:
case CalpontSystemCatalog::DATETIME:
{
func.reset(new WF_min_max<uint64_t>(id, name));
break;
}
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
{
func.reset(new WF_min_max<double>(id, name));
break;
}
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
{
func.reset(new WF_min_max<float>(id, name));
break;
}
default:
{
func.reset(new WF_min_max<string>(id, name));
break;
}
}
return func;
}
template<typename T>
WindowFunctionType* WF_min_max<T>::clone() const
{
return new WF_min_max<T>(*this);
return new WF_min_max<T>(*this);
}
template<typename T>
void WF_min_max<T>::resetData()
{
fCount = 0;
fCount = 0;
WindowFunctionType::resetData();
WindowFunctionType::resetData();
}
template<typename T>
void WF_min_max<T>::operator()(int64_t b, int64_t e, int64_t c)
{
// for unbounded - current row special handling
if (fPrev >= b && fPrev < c)
b = c;
else if (fPrev <= e && fPrev > c)
e = c;
// for unbounded - current row special handling
if (fPrev >= b && fPrev < c)
b = c;
else if (fPrev <= e && fPrev > c)
e = c;
uint64_t colIn = fFieldIndex[1];
for (int64_t i = b; i <= e; i++)
{
if (i % 1000 == 0 && fStep->cancelled())
break;
uint64_t colIn = fFieldIndex[1];
fRow.setData(getPointer(fRowData->at(i)));
if (fRow.isNullValue(colIn) == true)
continue;
for (int64_t i = b; i <= e; i++)
{
if (i % 1000 == 0 && fStep->cancelled())
break;
T valIn;
getValue(colIn, valIn);
if ((fCount == 0) ||
(valIn < fValue && fFunctionId == WF__MIN) ||
(valIn > fValue && fFunctionId == WF__MAX))
{
fValue = valIn;
}
fRow.setData(getPointer(fRowData->at(i)));
fCount++;
}
if (fRow.isNullValue(colIn) == true)
continue;
T* v = ((fCount > 0) ? &fValue : NULL);
setValue(fRow.getColType(fFieldIndex[0]), b, e, c, v);
T valIn;
getValue(colIn, valIn);
fPrev = c;
if ((fCount == 0) ||
(valIn < fValue && fFunctionId == WF__MIN) ||
(valIn > fValue && fFunctionId == WF__MAX))
{
fValue = valIn;
}
fCount++;
}
T* v = ((fCount > 0) ? &fValue : NULL);
setValue(fRow.getColType(fFieldIndex[0]), b, e, c, v);
fPrev = c;
}

View File

@ -32,18 +32,21 @@ template<typename T>
class WF_min_max : public WindowFunctionType
{
public:
WF_min_max(int id, const std::string& name) : WindowFunctionType(id, name) {resetData();}
WF_min_max(int id, const std::string& name) : WindowFunctionType(id, name)
{
resetData();
}
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
static boost::shared_ptr<WindowFunctionType> makeFunction(int, const string&, int);
static boost::shared_ptr<WindowFunctionType> makeFunction(int, const string&, int);
protected:
T fValue;
uint64_t fCount;
T fValue;
uint64_t fCount;
};

View File

@ -54,193 +54,212 @@ namespace windowfunction
template<typename T>
boost::shared_ptr<WindowFunctionType> WF_nth_value<T>::makeFunction(int id, const string& name, int ct)
{
boost::shared_ptr<WindowFunctionType> func;
switch (ct)
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
{
func.reset(new WF_nth_value<int64_t>(id, name));
break;
}
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UDECIMAL:
case CalpontSystemCatalog::DATE:
case CalpontSystemCatalog::DATETIME:
{
func.reset(new WF_nth_value<uint64_t>(id, name));
break;
}
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
{
func.reset(new WF_nth_value<double>(id, name));
break;
}
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
{
func.reset(new WF_nth_value<float>(id, name));
break;
}
default:
{
func.reset(new WF_nth_value<string>(id, name));
break;
}
}
boost::shared_ptr<WindowFunctionType> func;
return func;
switch (ct)
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
{
func.reset(new WF_nth_value<int64_t>(id, name));
break;
}
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UDECIMAL:
case CalpontSystemCatalog::DATE:
case CalpontSystemCatalog::DATETIME:
{
func.reset(new WF_nth_value<uint64_t>(id, name));
break;
}
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
{
func.reset(new WF_nth_value<double>(id, name));
break;
}
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
{
func.reset(new WF_nth_value<float>(id, name));
break;
}
default:
{
func.reset(new WF_nth_value<string>(id, name));
break;
}
}
return func;
}
template<typename T>
WindowFunctionType* WF_nth_value<T>::clone() const
{
return new WF_nth_value<T>(*this);
return new WF_nth_value<T>(*this);
}
template<typename T>
void WF_nth_value<T>::resetData()
{
WindowFunctionType::resetData();
WindowFunctionType::resetData();
}
template<typename T>
void WF_nth_value<T>::parseParms(const std::vector<execplan::SRCP>& parms)
{
// parms[0]: value-expr
// skip
// parms[0]: value-expr
// skip
// parms[1]: nth value
ConstantColumn* cc = dynamic_cast<ConstantColumn*>(parms[1].get());
if (cc != NULL)
{
fNthNull = false;
fNth = cc->getIntVal(fRow, fNthNull); // row not used, no need to setData.
if (fNth <= 0)
{
ostringstream oss;
oss << fNth;
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ERR_WF_ARG_OUT_OF_RANGE,
oss.str()), ERR_WF_ARG_OUT_OF_RANGE);
}
}
// parms[1]: nth value
ConstantColumn* cc = dynamic_cast<ConstantColumn*>(parms[1].get());
// parms[2]: from first | from last
bool isNull = false;
cc = dynamic_cast<ConstantColumn*>(parms[2].get());
idbassert(cc != NULL);
fFromFirst = (cc->getIntVal(fRow, isNull) > 0);
if (cc != NULL)
{
fNthNull = false;
fNth = cc->getIntVal(fRow, fNthNull); // row not used, no need to setData.
// parms[3]: respect null | ignore null
cc = dynamic_cast<ConstantColumn*>(parms[3].get());
idbassert(cc != NULL);
fRespectNulls = (cc->getIntVal(fRow, isNull) > 0);
if (fNth <= 0)
{
ostringstream oss;
oss << fNth;
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ERR_WF_ARG_OUT_OF_RANGE,
oss.str()), ERR_WF_ARG_OUT_OF_RANGE);
}
}
// parms[2]: from first | from last
bool isNull = false;
cc = dynamic_cast<ConstantColumn*>(parms[2].get());
idbassert(cc != NULL);
fFromFirst = (cc->getIntVal(fRow, isNull) > 0);
// parms[3]: respect null | ignore null
cc = dynamic_cast<ConstantColumn*>(parms[3].get());
idbassert(cc != NULL);
fRespectNulls = (cc->getIntVal(fRow, isNull) > 0);
}
template<typename T>
void WF_nth_value<T>::operator()(int64_t b, int64_t e, int64_t c)
{
int64_t s = b;
int64_t t = e;
if (c != WF__BOUND_ALL)
s = t = c;
int64_t s = b;
int64_t t = e;
for (int64_t c = s; c <= t; c++)
{
if (c % 1000 == 0 && fStep->cancelled())
break;
if (c != WF__BOUND_ALL)
s = t = c;
int64_t idx = fFieldIndex[2];
fRow.setData(getPointer(fRowData->at(c)));
if (idx != -1)
{
double tmp = 1.0;
fNthNull = fRow.isNullValue(idx);
if (!fNthNull)
{
implicit2T(idx, tmp, 0);
if (tmp <= 0)
{
ostringstream oss;
oss << tmp;
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ERR_WF_ARG_OUT_OF_RANGE,
oss.str()), ERR_WF_ARG_OUT_OF_RANGE);
}
for (int64_t c = s; c <= t; c++)
{
if (c % 1000 == 0 && fStep->cancelled())
break;
if (tmp > e) // prevent integer overflow
tmp = e + 1;
int64_t idx = fFieldIndex[2];
fRow.setData(getPointer(fRowData->at(c)));
fNth = (int64_t) tmp;
}
}
if (idx != -1)
{
double tmp = 1.0;
fNthNull = fRow.isNullValue(idx);
if (!fNthNull)
{
implicit2T(idx, tmp, 0);
if (tmp <= 0)
{
ostringstream oss;
oss << tmp;
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ERR_WF_ARG_OUT_OF_RANGE,
oss.str()), ERR_WF_ARG_OUT_OF_RANGE);
}
if (tmp > e) // prevent integer overflow
tmp = e + 1;
fNth = (int64_t) tmp;
}
}
bool isNull = true;
if ((!fNthNull) && ((b + fNth - 1) <= e))
{
uint64_t colIn = fFieldIndex[1];
if (fFromFirst)
{
int64_t k = b;
fRow.setData(getPointer(fRowData->at(k)));
if (fRespectNulls == false && fRow.isNullValue(colIn) == true)
{
while (++k < e)
{
fRow.setData(getPointer(fRowData->at(k)));
if (fRow.isNullValue(colIn) == false)
break;
}
}
bool isNull = true;
int64_t n = k + fNth - 1;
if (n <= e)
{
fRow.setData(getPointer(fRowData->at(n)));
getValue(colIn, fValue);
isNull = fRow.isNullValue(colIn);
}
}
else // from last
{
int64_t k = e;
fRow.setData(getPointer(fRowData->at(k)));
if (fRespectNulls == false && fRow.isNullValue(colIn) == true)
{
while (--k > b)
{
fRow.setData(getPointer(fRowData->at(k)));
if (fRow.isNullValue(colIn) == false)
break;
}
}
if ((!fNthNull) && ((b + fNth - 1) <= e))
{
uint64_t colIn = fFieldIndex[1];
int64_t n = k - fNth + 1;
if (n >= b)
{
fRow.setData(getPointer(fRowData->at(n)));
getValue(colIn, fValue);
isNull = fRow.isNullValue(colIn);
}
}
}
if (fFromFirst)
{
int64_t k = b;
fRow.setData(getPointer(fRowData->at(k)));
T* v = (isNull) ? NULL : &fValue;
setValue(fRow.getColType(fFieldIndex[0]), b, e, c, v);
}
if (fRespectNulls == false && fRow.isNullValue(colIn) == true)
{
while (++k < e)
{
fRow.setData(getPointer(fRowData->at(k)));
if (fRow.isNullValue(colIn) == false)
break;
}
}
int64_t n = k + fNth - 1;
if (n <= e)
{
fRow.setData(getPointer(fRowData->at(n)));
getValue(colIn, fValue);
isNull = fRow.isNullValue(colIn);
}
}
else // from last
{
int64_t k = e;
fRow.setData(getPointer(fRowData->at(k)));
if (fRespectNulls == false && fRow.isNullValue(colIn) == true)
{
while (--k > b)
{
fRow.setData(getPointer(fRowData->at(k)));
if (fRow.isNullValue(colIn) == false)
break;
}
}
int64_t n = k - fNth + 1;
if (n >= b)
{
fRow.setData(getPointer(fRowData->at(n)));
getValue(colIn, fValue);
isNull = fRow.isNullValue(colIn);
}
}
}
T* v = (isNull) ? NULL : &fValue;
setValue(fRow.getColType(fFieldIndex[0]), b, e, c, v);
}
}

View File

@ -32,22 +32,25 @@ template<typename T>
class WF_nth_value : public WindowFunctionType
{
public:
WF_nth_value(int id, const std::string& name) : WindowFunctionType(id, name) {resetData();}
WF_nth_value(int id, const std::string& name) : WindowFunctionType(id, name)
{
resetData();
}
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
void parseParms(const std::vector<execplan::SRCP>&);
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
void parseParms(const std::vector<execplan::SRCP>&);
static boost::shared_ptr<WindowFunctionType> makeFunction(int, const string&, int);
static boost::shared_ptr<WindowFunctionType> makeFunction(int, const string&, int);
protected:
T fValue;
int64_t fNth;
bool fNthNull;
bool fFromFirst; // from first | from last
bool fRespectNulls; // respect null | ignore null
T fValue;
int64_t fNth;
bool fNthNull;
bool fFromFirst; // from first | from last
bool fRespectNulls; // respect null | ignore null
};

View File

@ -56,104 +56,111 @@ namespace windowfunction
boost::shared_ptr<WindowFunctionType> WF_ntile::makeFunction(int id, const string& name, int ct)
{
boost::shared_ptr<WindowFunctionType> func(new WF_ntile(id, name));
return func;
boost::shared_ptr<WindowFunctionType> func(new WF_ntile(id, name));
return func;
}
WindowFunctionType* WF_ntile::clone() const
{
return new WF_ntile(*this);
return new WF_ntile(*this);
}
void WF_ntile::resetData()
{
WindowFunctionType::resetData();
WindowFunctionType::resetData();
}
void WF_ntile::parseParms(const std::vector<execplan::SRCP>& parms)
{
// parms[0]: nt
ConstantColumn* cc = dynamic_cast<ConstantColumn*>(parms[0].get());
if (cc != NULL)
{
fNtileNull = false;
fNtile = cc->getIntVal(fRow, fNtileNull); // row not used, no need to setData.
if (!fNtileNull && fNtile <= 0)
{
ostringstream oss;
oss << fNtile;
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ERR_WF_ARG_OUT_OF_RANGE,
oss.str()), ERR_WF_ARG_OUT_OF_RANGE);
}
}
// parms[0]: nt
ConstantColumn* cc = dynamic_cast<ConstantColumn*>(parms[0].get());
if (cc != NULL)
{
fNtileNull = false;
fNtile = cc->getIntVal(fRow, fNtileNull); // row not used, no need to setData.
if (!fNtileNull && fNtile <= 0)
{
ostringstream oss;
oss << fNtile;
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ERR_WF_ARG_OUT_OF_RANGE,
oss.str()), ERR_WF_ARG_OUT_OF_RANGE);
}
}
}
void WF_ntile::operator()(int64_t b, int64_t e, int64_t c)
{
int64_t idx = fFieldIndex[1];
if (idx != -1)
{
fRow.setData(getPointer(fRowData->at(b)));
if (idx != -1)
{
double tmp = 1.0;
fNtileNull = fRow.isNullValue(idx);
if (!fNtileNull)
implicit2T(idx, tmp, 0);
int64_t idx = fFieldIndex[1];
if (!fNtileNull && tmp <= 0)
{
ostringstream oss;
oss << tmp;
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ERR_WF_ARG_OUT_OF_RANGE,
oss.str()), ERR_WF_ARG_OUT_OF_RANGE);
}
if (idx != -1)
{
fRow.setData(getPointer(fRowData->at(b)));
if (tmp > e) // prevent integer overflow
tmp = e + 1;
if (idx != -1)
{
double tmp = 1.0;
fNtileNull = fRow.isNullValue(idx);
fNtile = (int64_t) tmp;
}
}
if (!fNtileNull)
implicit2T(idx, tmp, 0);
c = b;
if (!fNtileNull)
{
int64_t rowPerBucket = (e - b + 1) / fNtile;
int64_t n = rowPerBucket * fNtile;
int64_t x = (e-b+1) - n; // extra
int64_t y = 0;
int64_t z = 0;
if (!fNtileNull && tmp <= 0)
{
ostringstream oss;
oss << tmp;
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ERR_WF_ARG_OUT_OF_RANGE,
oss.str()), ERR_WF_ARG_OUT_OF_RANGE);
}
while (c <= e)
{
if (c % 1000 == 0 && fStep->cancelled())
break;
if (tmp > e) // prevent integer overflow
tmp = e + 1;
y = rowPerBucket + ((x-- > 0) ? 1 : 0);
z++;
for (int64_t i = 0; i < y && c <= e; i++)
{
fRow.setData(getPointer(fRowData->at(c++)));
setIntValue(fFieldIndex[0], z);
}
}
}
else
{
while (c <= e)
{
if (c % 1000 == 0 && fStep->cancelled())
break;
fNtile = (int64_t) tmp;
}
}
fRow.setData(getPointer(fRowData->at(c++)));
setIntValue(fFieldIndex[0], joblist::BIGINTNULL);
}
}
c = b;
if (!fNtileNull)
{
int64_t rowPerBucket = (e - b + 1) / fNtile;
int64_t n = rowPerBucket * fNtile;
int64_t x = (e - b + 1) - n; // extra
int64_t y = 0;
int64_t z = 0;
while (c <= e)
{
if (c % 1000 == 0 && fStep->cancelled())
break;
y = rowPerBucket + ((x-- > 0) ? 1 : 0);
z++;
for (int64_t i = 0; i < y && c <= e; i++)
{
fRow.setData(getPointer(fRowData->at(c++)));
setIntValue(fFieldIndex[0], z);
}
}
}
else
{
while (c <= e)
{
if (c % 1000 == 0 && fStep->cancelled())
break;
fRow.setData(getPointer(fRowData->at(c++)));
setIntValue(fFieldIndex[0], joblist::BIGINTNULL);
}
}
}

View File

@ -32,20 +32,23 @@ namespace windowfunction
class WF_ntile : public WindowFunctionType
{
public:
WF_ntile(int id, const std::string& name) : WindowFunctionType(id, name) {resetData();}
WF_ntile(int id, const std::string& name) : WindowFunctionType(id, name)
{
resetData();
}
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
void parseParms(const std::vector<execplan::SRCP>&);
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
void parseParms(const std::vector<execplan::SRCP>&);
static boost::shared_ptr<WindowFunctionType> makeFunction(int, const string&, int);
static boost::shared_ptr<WindowFunctionType> makeFunction(int, const string&, int);
protected:
uint64_t fNtile;
bool fNtileNull;
uint64_t fNtile;
bool fNtileNull;
};

View File

@ -57,281 +57,301 @@ namespace windowfunction
template<typename T>
boost::shared_ptr<WindowFunctionType> WF_percentile<T>::makeFunction(int id, const string& name, int ct)
{
boost::shared_ptr<WindowFunctionType> func;
if (id == WF__PERCENTILE_DISC)
{
switch (ct)
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
{
func.reset(new WF_percentile<int64_t>(id, name));
break;
}
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UDECIMAL:
case CalpontSystemCatalog::DATE:
case CalpontSystemCatalog::DATETIME:
{
func.reset(new WF_percentile<uint64_t>(id, name));
break;
}
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
{
func.reset(new WF_percentile<double>(id, name));
break;
}
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
{
func.reset(new WF_percentile<float>(id, name));
break;
}
default:
{
if (id == WF__PERCENTILE_DISC)
{
func.reset(new WF_percentile<string>(id, name));
}
else
{
string errStr = name + "(" + colType2String[ct] + ")";
errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_INVALID_PARM_TYPE, errStr);
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_INVALID_PARM_TYPE);
}
break;
}
}
}
else
{
switch (ct)
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UDECIMAL:
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
{
func.reset(new WF_percentile<double>(id, name));
break;
}
default:
{
string errStr = name + "(" + colType2String[ct] + ")";
errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_INVALID_PARM_TYPE, errStr);
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_INVALID_PARM_TYPE);
break;
}
}
}
boost::shared_ptr<WindowFunctionType> func;
return func;
if (id == WF__PERCENTILE_DISC)
{
switch (ct)
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
{
func.reset(new WF_percentile<int64_t>(id, name));
break;
}
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UDECIMAL:
case CalpontSystemCatalog::DATE:
case CalpontSystemCatalog::DATETIME:
{
func.reset(new WF_percentile<uint64_t>(id, name));
break;
}
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
{
func.reset(new WF_percentile<double>(id, name));
break;
}
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
{
func.reset(new WF_percentile<float>(id, name));
break;
}
default:
{
if (id == WF__PERCENTILE_DISC)
{
func.reset(new WF_percentile<string>(id, name));
}
else
{
string errStr = name + "(" + colType2String[ct] + ")";
errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_INVALID_PARM_TYPE, errStr);
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_INVALID_PARM_TYPE);
}
break;
}
}
}
else
{
switch (ct)
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UDECIMAL:
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
{
func.reset(new WF_percentile<double>(id, name));
break;
}
default:
{
string errStr = name + "(" + colType2String[ct] + ")";
errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_INVALID_PARM_TYPE, errStr);
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_INVALID_PARM_TYPE);
break;
}
}
}
return func;
}
template<typename T>
WindowFunctionType* WF_percentile<T>::clone() const
{
return new WF_percentile(*this);
return new WF_percentile(*this);
}
template<typename T>
void WF_percentile<T>::resetData()
{
WindowFunctionType::resetData();
WindowFunctionType::resetData();
}
template<typename T>
void WF_percentile<T>::parseParms(const std::vector<execplan::SRCP>& parms)
{
// parms[0]: nve
ConstantColumn* cc = dynamic_cast<ConstantColumn*>(parms[0].get());
if (cc != NULL)
{
fNveNull = false;
fNve = cc->getDoubleVal(fRow, fNveNull); // row not used, no need to setData.
if (!fNveNull && (fNve < 0 || fNve > 1))
{
ostringstream oss;
oss << fNve;
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ERR_WF_ARG_OUT_OF_RANGE,
oss.str()), ERR_WF_ARG_OUT_OF_RANGE);
}
}
// parms[0]: nve
ConstantColumn* cc = dynamic_cast<ConstantColumn*>(parms[0].get());
// workaround for the within group order by column index
idbassert(fPeer->fIndex.size() > 0);
fFieldIndex.push_back(fPeer->fIndex[0]);
if (cc != NULL)
{
fNveNull = false;
fNve = cc->getDoubleVal(fRow, fNveNull); // row not used, no need to setData.
if (!fNveNull && (fNve < 0 || fNve > 1))
{
ostringstream oss;
oss << fNve;
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ERR_WF_ARG_OUT_OF_RANGE,
oss.str()), ERR_WF_ARG_OUT_OF_RANGE);
}
}
// workaround for the within group order by column index
idbassert(fPeer->fIndex.size() > 0);
fFieldIndex.push_back(fPeer->fIndex[0]);
}
template<typename T>
void WF_percentile<T>::operator()(int64_t b, int64_t e, int64_t c)
{
int64_t idx = fFieldIndex[1];
fRow.setData(getPointer(fRowData->at(b)));
if (idx != -1)
{
if (idx != -1)
{
fNveNull = fRow.isNullValue(idx);
implicit2T(idx, fNve, 0);
if (!fNveNull && (fNve < 0 || fNve > 1))
{
ostringstream oss;
oss << fNve;
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ERR_WF_ARG_OUT_OF_RANGE,
oss.str()), ERR_WF_ARG_OUT_OF_RANGE);
}
}
}
int64_t idx = fFieldIndex[1];
fRow.setData(getPointer(fRowData->at(b)));
if (fNveNull)
{
for (c = b; c <= e; c++)
{
if (c % 1000 == 0 && fStep->cancelled())
break;
if (idx != -1)
{
if (idx != -1)
{
fNveNull = fRow.isNullValue(idx);
implicit2T(idx, fNve, 0);
fRow.setData(getPointer(fRowData->at(c)));
setValue(fRow.getColType(fFieldIndex[0]), b, e, c, (T*) NULL);
}
if (!fNveNull && (fNve < 0 || fNve > 1))
{
ostringstream oss;
oss << fNve;
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ERR_WF_ARG_OUT_OF_RANGE,
oss.str()), ERR_WF_ARG_OUT_OF_RANGE);
}
}
}
return;
}
if (fNveNull)
{
for (c = b; c <= e; c++)
{
if (c % 1000 == 0 && fStep->cancelled())
break;
idx = fFieldIndex[2];
int64_t rank = 0;
int64_t dups = 0;
int64_t b1 = -1;
int64_t e1 = -1;
scoped_array<int64_t> rk(new int64_t[e - b + 1]);
for (c = b; c <= e; c++)
{
if (c % 1000 == 0 && fStep->cancelled())
break;
fRow.setData(getPointer(fRowData->at(c)));
setValue(fRow.getColType(fFieldIndex[0]), b, e, c, (T*) NULL);
}
fRow.setData(getPointer(fRowData->at(c)));
if (fRow.isNullValue(idx))
continue;
return;
}
// ignore nulls
if (b1 == -1)
b1 = c;
e1 = c;
idx = fFieldIndex[2];
int64_t rank = 0;
int64_t dups = 0;
int64_t b1 = -1;
int64_t e1 = -1;
scoped_array<int64_t> rk(new int64_t[e - b + 1]);
if (fFunctionId == WF__PERCENTILE_DISC)
{
// need cume_rank
if (c != b &&
fPeer->operator()(getPointer(fRowData->at(c)), getPointer(fRowData->at(c-1))))
{
dups++;
}
else
{
rank++;
rank += dups;
dups = 0;
}
for (c = b; c <= e; c++)
{
if (c % 1000 == 0 && fStep->cancelled())
break;
rk[c-b] = rank;
}
}
fRow.setData(getPointer(fRowData->at(c)));
T* p = NULL;
T v;
int ct = (fFunctionId == WF__PERCENTILE_CONT) ?
CalpontSystemCatalog::DOUBLE : fRow.getColType(idx);
if (b1 != -1)
{
double cnt = (e1 - b1 + 1);
if (fFunctionId == WF__PERCENTILE_CONT)
{
// @bug5820, this "rn" is the normalized row number, not the real row number.
// Using real row number here will introduce a small calculation error in double result.
double rn = fNve * (cnt - 1);
double crn = ceil(rn);
double frn = floor(rn);
double vd = 0;
if (crn == rn && rn == frn)
{
fRow.setData(getPointer(fRowData->at((size_t) rn + (size_t) b1)));
implicit2T(idx, vd, 0);
}
else
{
double cv = 0.0, fv = 0.0;
fRow.setData(getPointer(fRowData->at((size_t) frn + (size_t) b1)));
implicit2T(idx, fv, 0);
fRow.setData(getPointer(fRowData->at((size_t) crn + (size_t) b1)));
implicit2T(idx, cv, 0);
vd = (crn - rn) * fv + (rn - frn) * cv;
}
if (fRow.isNullValue(idx))
continue;
v = *(reinterpret_cast<T*>(&vd));
p = &v;
}
else // (fFunctionId == WF__PERCENTILE_DISC)
{
int prevRank = ++rank + dups;
double cumeDist = 1;
fRow.setData(getPointer(fRowData->at(e1)));
for (c = e1; c >= b1; c--)
{
int currRank = rk[c-b];
if (currRank != prevRank)
{
cumeDist = ((double) (prevRank-1)) / cnt;
if (cumeDist < fNve)
break;
// ignore nulls
if (b1 == -1)
b1 = c;
prevRank = currRank;
}
}
e1 = c;
c++;
if (fFunctionId == WF__PERCENTILE_DISC)
{
// need cume_rank
if (c != b &&
fPeer->operator()(getPointer(fRowData->at(c)), getPointer(fRowData->at(c - 1))))
{
dups++;
}
else
{
rank++;
rank += dups;
dups = 0;
}
fRow.setData(getPointer(fRowData->at(c)));
getValue(idx, v);
rk[c - b] = rank;
}
}
p = &v;
}
}
T* p = NULL;
T v;
int ct = (fFunctionId == WF__PERCENTILE_CONT) ?
CalpontSystemCatalog::DOUBLE : fRow.getColType(idx);
for (c = b; c <= e; c++)
{
if (c % 1000 == 0 && fStep->cancelled())
break;
if (b1 != -1)
{
double cnt = (e1 - b1 + 1);
fRow.setData(getPointer(fRowData->at(c)));
setValue(ct, b, e, c, p);
}
if (fFunctionId == WF__PERCENTILE_CONT)
{
// @bug5820, this "rn" is the normalized row number, not the real row number.
// Using real row number here will introduce a small calculation error in double result.
double rn = fNve * (cnt - 1);
double crn = ceil(rn);
double frn = floor(rn);
double vd = 0;
if (crn == rn && rn == frn)
{
fRow.setData(getPointer(fRowData->at((size_t) rn + (size_t) b1)));
implicit2T(idx, vd, 0);
}
else
{
double cv = 0.0, fv = 0.0;
fRow.setData(getPointer(fRowData->at((size_t) frn + (size_t) b1)));
implicit2T(idx, fv, 0);
fRow.setData(getPointer(fRowData->at((size_t) crn + (size_t) b1)));
implicit2T(idx, cv, 0);
vd = (crn - rn) * fv + (rn - frn) * cv;
}
v = *(reinterpret_cast<T*>(&vd));
p = &v;
}
else // (fFunctionId == WF__PERCENTILE_DISC)
{
int prevRank = ++rank + dups;
double cumeDist = 1;
fRow.setData(getPointer(fRowData->at(e1)));
for (c = e1; c >= b1; c--)
{
int currRank = rk[c - b];
if (currRank != prevRank)
{
cumeDist = ((double) (prevRank - 1)) / cnt;
if (cumeDist < fNve)
break;
prevRank = currRank;
}
}
c++;
fRow.setData(getPointer(fRowData->at(c)));
getValue(idx, v);
p = &v;
}
}
for (c = b; c <= e; c++)
{
if (c % 1000 == 0 && fStep->cancelled())
break;
fRow.setData(getPointer(fRowData->at(c)));
setValue(ct, b, e, c, p);
}
}

View File

@ -33,20 +33,23 @@ template<typename T>
class WF_percentile : public WindowFunctionType
{
public:
WF_percentile(int id, const std::string& name) : WindowFunctionType(id, name) {resetData();}
WF_percentile(int id, const std::string& name) : WindowFunctionType(id, name)
{
resetData();
}
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
void parseParms(const std::vector<execplan::SRCP>&);
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
void parseParms(const std::vector<execplan::SRCP>&);
static boost::shared_ptr<WindowFunctionType> makeFunction(int, const string&, int);
static boost::shared_ptr<WindowFunctionType> makeFunction(int, const string&, int);
protected:
double fNve;
bool fNveNull;
double fNve;
bool fNveNull;
};

View File

@ -55,93 +55,100 @@ namespace windowfunction
boost::shared_ptr<WindowFunctionType> WF_ranking::makeFunction(int id, const string& name, int ct)
{
boost::shared_ptr<WindowFunctionType> func(new WF_ranking(id, name));
return func;
boost::shared_ptr<WindowFunctionType> func(new WF_ranking(id, name));
return func;
}
WindowFunctionType* WF_ranking::clone() const
{
return new WF_ranking(*this);
return new WF_ranking(*this);
}
void WF_ranking::resetData()
{
fRank = 0;
fDups = 0;
fRank = 0;
fDups = 0;
WindowFunctionType::resetData();
WindowFunctionType::resetData();
}
void WF_ranking::operator()(int64_t b, int64_t e, int64_t c)
{
// one row handling
if (fPartition.first == fPartition.second)
{
fRow.setData(getPointer(fRowData->at(fPartition.first)));
int64_t r = (fFunctionId == WF__PERCENT_RANK) ? 0 : 1;
if (fFunctionId == WF__RANK || fFunctionId == WF__DENSE_RANK)
setIntValue(fFieldIndex[0], r);
else
setDoubleValue(fFieldIndex[0], r);
// one row handling
if (fPartition.first == fPartition.second)
{
fRow.setData(getPointer(fRowData->at(fPartition.first)));
int64_t r = (fFunctionId == WF__PERCENT_RANK) ? 0 : 1;
return;
}
if (fFunctionId == WF__RANK || fFunctionId == WF__DENSE_RANK)
setIntValue(fFieldIndex[0], r);
else
setDoubleValue(fFieldIndex[0], r);
// more than one row, e > b
b = fPartition.first;
e = fPartition.second;
double n1 = e - b; // count(*) - 1, n will not be 0.
for (c = b; c <= e; c++)
{
if (c % 1000 == 0 && fStep->cancelled())
break;
return;
}
if (c != b &&
fPeer->operator()(getPointer(fRowData->at(c)), getPointer(fRowData->at(c-1))))
{
fDups++;
}
else
{
fRank++;
if (fFunctionId != WF__DENSE_RANK)
fRank += fDups;
fDups = 0;
}
// more than one row, e > b
b = fPartition.first;
e = fPartition.second;
double n1 = e - b; // count(*) - 1, n will not be 0.
fRow.setData(getPointer(fRowData->at(c)));
if (fFunctionId != WF__PERCENT_RANK)
setIntValue(fFieldIndex[0], fRank);
else
setDoubleValue(fFieldIndex[0], (fRank-1)/n1);
}
for (c = b; c <= e; c++)
{
if (c % 1000 == 0 && fStep->cancelled())
break;
// Two-pass, need to find peers.
if (fFunctionId == WF__CUME_DIST)
{
int prevRank = ++fRank + fDups; // hypothetical row at (e+1)
double n0 = (e - b + 1); // count(*)
double cumeDist = 1;
fRow.setData(getPointer(fRowData->at(e)));
for (c = e; c >= b; c--)
{
if (c % 1000 == 0 && fStep->cancelled())
break;
if (c != b &&
fPeer->operator()(getPointer(fRowData->at(c)), getPointer(fRowData->at(c - 1))))
{
fDups++;
}
else
{
fRank++;
fRow.setData(getPointer(fRowData->at(c)));
int currRank = getIntValue(fFieldIndex[0]);
if (currRank != prevRank)
{
cumeDist = ((double) (prevRank-1)) / n0;
prevRank = currRank;
}
if (fFunctionId != WF__DENSE_RANK)
fRank += fDups;
setDoubleValue(fFieldIndex[0], cumeDist);
}
}
fDups = 0;
}
fRow.setData(getPointer(fRowData->at(c)));
if (fFunctionId != WF__PERCENT_RANK)
setIntValue(fFieldIndex[0], fRank);
else
setDoubleValue(fFieldIndex[0], (fRank - 1) / n1);
}
// Two-pass, need to find peers.
if (fFunctionId == WF__CUME_DIST)
{
int prevRank = ++fRank + fDups; // hypothetical row at (e+1)
double n0 = (e - b + 1); // count(*)
double cumeDist = 1;
fRow.setData(getPointer(fRowData->at(e)));
for (c = e; c >= b; c--)
{
if (c % 1000 == 0 && fStep->cancelled())
break;
fRow.setData(getPointer(fRowData->at(c)));
int currRank = getIntValue(fFieldIndex[0]);
if (currRank != prevRank)
{
cumeDist = ((double) (prevRank - 1)) / n0;
prevRank = currRank;
}
setDoubleValue(fFieldIndex[0], cumeDist);
}
}
}

View File

@ -32,19 +32,22 @@ namespace windowfunction
class WF_ranking : public WindowFunctionType
{
public:
WF_ranking(int id, const std::string& name) : WindowFunctionType(id, name) {resetData();}
WF_ranking(int id, const std::string& name) : WindowFunctionType(id, name)
{
resetData();
}
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
static boost::shared_ptr<WindowFunctionType> makeFunction(int, const string&, int);
static boost::shared_ptr<WindowFunctionType> makeFunction(int, const string&, int);
protected:
uint64_t fRank;
uint64_t fDups;
uint64_t fRank;
uint64_t fDups;
};

View File

@ -55,39 +55,40 @@ namespace windowfunction
boost::shared_ptr<WindowFunctionType> WF_row_number::makeFunction(int id, const string& name, int ct)
{
boost::shared_ptr<WindowFunctionType> func(new WF_row_number(id, name));
return func;
boost::shared_ptr<WindowFunctionType> func(new WF_row_number(id, name));
return func;
}
WindowFunctionType* WF_row_number::clone() const
{
return new WF_row_number(*this);
return new WF_row_number(*this);
}
void WF_row_number::resetData()
{
fRowNumber= 0;
fRowNumber = 0;
WindowFunctionType::resetData();
WindowFunctionType::resetData();
}
void WF_row_number::operator()(int64_t b, int64_t e, int64_t c)
{
b = fPartition.first;
e = fPartition.second;
for (c = b; c <= e; c++)
{
if (c % 1000 == 0 && fStep->cancelled())
break;
b = fPartition.first;
e = fPartition.second;
fRow.setData(getPointer(fRowData->at(c)));
fRowNumber++;
for (c = b; c <= e; c++)
{
if (c % 1000 == 0 && fStep->cancelled())
break;
setIntValue(fFieldIndex[0], fRowNumber);
}
fRow.setData(getPointer(fRowData->at(c)));
fRowNumber++;
setIntValue(fFieldIndex[0], fRowNumber);
}
}

View File

@ -32,18 +32,21 @@ namespace windowfunction
class WF_row_number : public WindowFunctionType
{
public:
WF_row_number(int id, const std::string& name) : WindowFunctionType(id, name) {resetData();}
WF_row_number(int id, const std::string& name) : WindowFunctionType(id, name)
{
resetData();
}
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
static boost::shared_ptr<WindowFunctionType> makeFunction(int, const string&, int);
static boost::shared_ptr<WindowFunctionType> makeFunction(int, const string&, int);
protected:
uint64_t fRowNumber;
uint64_t fRowNumber;
};

View File

@ -56,148 +56,156 @@ namespace windowfunction
template<typename T>
boost::shared_ptr<WindowFunctionType> WF_stats<T>::makeFunction(int id, const string& name, int ct)
{
boost::shared_ptr<WindowFunctionType> func;
switch (ct)
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
{
func.reset(new WF_stats<int64_t>(id, name));
break;
}
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UDECIMAL:
{
func.reset(new WF_stats<uint64_t>(id, name));
break;
}
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
{
func.reset(new WF_stats<double>(id, name));
break;
}
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
{
func.reset(new WF_stats<float>(id, name));
break;
}
default:
{
string errStr = name + "(" + colType2String[ct] + ")";
errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_INVALID_PARM_TYPE, errStr);
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_INVALID_PARM_TYPE);
boost::shared_ptr<WindowFunctionType> func;
break;
}
}
switch (ct)
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
{
func.reset(new WF_stats<int64_t>(id, name));
break;
}
return func;
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UDECIMAL:
{
func.reset(new WF_stats<uint64_t>(id, name));
break;
}
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
{
func.reset(new WF_stats<double>(id, name));
break;
}
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
{
func.reset(new WF_stats<float>(id, name));
break;
}
default:
{
string errStr = name + "(" + colType2String[ct] + ")";
errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_INVALID_PARM_TYPE, errStr);
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_INVALID_PARM_TYPE);
break;
}
}
return func;
}
template<typename T>
WindowFunctionType* WF_stats<T>::clone() const
{
return new WF_stats<T>(*this);
return new WF_stats<T>(*this);
}
template<typename T>
void WF_stats<T>::resetData()
{
fSum1 = 0;
fSum2 = 0;
fCount = 0;
fStats = 0.0;
fSum1 = 0;
fSum2 = 0;
fCount = 0;
fStats = 0.0;
WindowFunctionType::resetData();
WindowFunctionType::resetData();
}
template<typename T>
void WF_stats<T>::operator()(int64_t b, int64_t e, int64_t c)
{
if ((fFrameUnit == WF__FRAME_ROWS) ||
(fPrev == -1) ||
(!fPeer->operator()(getPointer(fRowData->at(c)), getPointer(fRowData->at(fPrev)))))
{
// for unbounded - current row special handling
if (fPrev >= b && fPrev < c)
b = c;
else if (fPrev <= e && fPrev > c)
e = c;
if ((fFrameUnit == WF__FRAME_ROWS) ||
(fPrev == -1) ||
(!fPeer->operator()(getPointer(fRowData->at(c)), getPointer(fRowData->at(fPrev)))))
{
// for unbounded - current row special handling
if (fPrev >= b && fPrev < c)
b = c;
else if (fPrev <= e && fPrev > c)
e = c;
uint64_t colIn = fFieldIndex[1];
for (int64_t i = b; i <= e; i++)
{
if (i % 1000 == 0 && fStep->cancelled())
break;
uint64_t colIn = fFieldIndex[1];
fRow.setData(getPointer(fRowData->at(i)));
if (fRow.isNullValue(colIn) == true)
continue;
for (int64_t i = b; i <= e; i++)
{
if (i % 1000 == 0 && fStep->cancelled())
break;
T valIn;
getValue(colIn, valIn);
long double val = (long double) valIn;
fRow.setData(getPointer(fRowData->at(i)));
fSum1 += val;
fSum2 += val * val;
fCount++;
}
if (fRow.isNullValue(colIn) == true)
continue;
if ((fCount > 0) &&
!(fCount == 1 && (fFunctionId == WF__STDDEV_SAMP || fFunctionId == WF__VAR_SAMP)))
{
int scale = fRow.getScale(colIn);
long double factor = pow(10.0, scale);
if (scale != 0) // adjust the scale if necessary
{
fSum1 /= factor;
fSum2 /= factor*factor;
}
T valIn;
getValue(colIn, valIn);
long double val = (long double) valIn;
long double stat = fSum1 * fSum1 / fCount;
stat = fSum2 - stat;
fSum1 += val;
fSum2 += val * val;
fCount++;
}
if (fFunctionId == WF__STDDEV_POP)
stat = sqrt(stat / fCount);
else if (fFunctionId == WF__STDDEV_SAMP)
stat = sqrt(stat / (fCount - 1));
else if (fFunctionId == WF__VAR_POP)
stat = stat / fCount;
else if (fFunctionId == WF__VAR_SAMP)
stat = stat / (fCount - 1);
if ((fCount > 0) &&
!(fCount == 1 && (fFunctionId == WF__STDDEV_SAMP || fFunctionId == WF__VAR_SAMP)))
{
int scale = fRow.getScale(colIn);
long double factor = pow(10.0, scale);
fStats = (double) stat;
}
}
if (scale != 0) // adjust the scale if necessary
{
fSum1 /= factor;
fSum2 /= factor * factor;
}
if (fCount == 0)
{
setValue(CalpontSystemCatalog::DOUBLE, b, e, c, (double*) NULL);
}
else if (fCount == 1 && (fFunctionId == WF__STDDEV_SAMP || fFunctionId == WF__VAR_SAMP))
{
setValue(CalpontSystemCatalog::DOUBLE, b, e, c, (double*) NULL);
}
else
{
setValue(CalpontSystemCatalog::DOUBLE, b, e, c, &fStats);
}
long double stat = fSum1 * fSum1 / fCount;
stat = fSum2 - stat;
fPrev = c;
if (fFunctionId == WF__STDDEV_POP)
stat = sqrt(stat / fCount);
else if (fFunctionId == WF__STDDEV_SAMP)
stat = sqrt(stat / (fCount - 1));
else if (fFunctionId == WF__VAR_POP)
stat = stat / fCount;
else if (fFunctionId == WF__VAR_SAMP)
stat = stat / (fCount - 1);
fStats = (double) stat;
}
}
if (fCount == 0)
{
setValue(CalpontSystemCatalog::DOUBLE, b, e, c, (double*) NULL);
}
else if (fCount == 1 && (fFunctionId == WF__STDDEV_SAMP || fFunctionId == WF__VAR_SAMP))
{
setValue(CalpontSystemCatalog::DOUBLE, b, e, c, (double*) NULL);
}
else
{
setValue(CalpontSystemCatalog::DOUBLE, b, e, c, &fStats);
}
fPrev = c;
}

View File

@ -32,20 +32,23 @@ template<typename T>
class WF_stats : public WindowFunctionType
{
public:
WF_stats(int id, const std::string& name) : WindowFunctionType(id, name) {resetData();}
WF_stats(int id, const std::string& name) : WindowFunctionType(id, name)
{
resetData();
}
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
static boost::shared_ptr<WindowFunctionType> makeFunction(int, const string&, int);
static boost::shared_ptr<WindowFunctionType> makeFunction(int, const string&, int);
protected:
long double fSum1;
long double fSum2;
uint64_t fCount;
double fStats;
long double fSum1;
long double fSum2;
uint64_t fCount;
double fStats;
};

View File

@ -62,88 +62,91 @@ void checkSumLimit(T sum, T val)
template<>
void checkSumLimit<int64_t>(int64_t sum, int64_t val)
{
if (((sum >= 0) && ((numeric_limits<int64_t>::max() - sum) < val)) ||
((sum < 0) && ((numeric_limits<int64_t>::min() - sum) > val)))
{
string errStr = "SUM(int):";
if (((sum >= 0) && ((numeric_limits<int64_t>::max() - sum) < val)) ||
((sum < 0) && ((numeric_limits<int64_t>::min() - sum) > val)))
{
string errStr = "SUM(int):";
ostringstream oss;
oss << sum << "+" << val;
if (sum > 0)
oss << " > " << numeric_limits<uint64_t>::max();
else
oss << " < " << numeric_limits<uint64_t>::min();
errStr += oss.str();
ostringstream oss;
oss << sum << "+" << val;
errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_OVERFLOW, errStr);
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_OVERFLOW);
}
if (sum > 0)
oss << " > " << numeric_limits<uint64_t>::max();
else
oss << " < " << numeric_limits<uint64_t>::min();
errStr += oss.str();
errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_OVERFLOW, errStr);
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_OVERFLOW);
}
}
template<>
void checkSumLimit<uint64_t>(uint64_t sum, uint64_t val)
{
if ((sum >= 0) && ((numeric_limits<uint64_t>::max() - sum) < val))
{
string errStr = "SUM(unsigned):";
if ((sum >= 0) && ((numeric_limits<uint64_t>::max() - sum) < val))
{
string errStr = "SUM(unsigned):";
ostringstream oss;
oss << sum << "+" << val << " > " << numeric_limits<uint64_t>::max();
errStr += oss.str();
ostringstream oss;
oss << sum << "+" << val << " > " << numeric_limits<uint64_t>::max();
errStr += oss.str();
errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_OVERFLOW, errStr);
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_OVERFLOW);
}
errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_OVERFLOW, errStr);
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_OVERFLOW);
}
}
template<typename T>
T calculateAvg(T sum, uint64_t count, int s)
{
T avg = ((long double) sum) / count;
return avg;
T avg = ((long double) sum) / count;
return avg;
}
long double avgWithLimit(long double sum, uint64_t count, int scale, long double u, long double l)
{
long double factor = pow(10.0, scale);
long double avg = sum / count;
avg *= factor;
avg += (avg < 0) ? (-0.5) : (0.5);
if (avg > u || avg < l)
{
string errStr = string("AVG") + (l < 0 ? "(int):" : "(unsign)");
ostringstream oss;
oss << avg;
errStr += oss.str();
long double factor = pow(10.0, scale);
long double avg = sum / count;
avg *= factor;
avg += (avg < 0) ? (-0.5) : (0.5);
errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_OVERFLOW, errStr);
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_OVERFLOW);
}
if (avg > u || avg < l)
{
string errStr = string("AVG") + (l < 0 ? "(int):" : "(unsign)");
ostringstream oss;
oss << avg;
errStr += oss.str();
return avg;
errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_OVERFLOW, errStr);
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_OVERFLOW);
}
return avg;
}
template<>
int64_t calculateAvg<int64_t>(int64_t sum, uint64_t count, int scale)
{
int64_t t = (int64_t) avgWithLimit(sum, count, scale,
numeric_limits<int64_t>::max(), numeric_limits<int64_t>::min());
return t;
int64_t t = (int64_t) avgWithLimit(sum, count, scale,
numeric_limits<int64_t>::max(), numeric_limits<int64_t>::min());
return t;
}
template<>
uint64_t calculateAvg<uint64_t>(uint64_t sum, uint64_t count, int scale)
{
uint64_t t = (uint64_t) avgWithLimit(sum, count, scale, numeric_limits<uint64_t>::max(), 0);
return t;
uint64_t t = (uint64_t) avgWithLimit(sum, count, scale, numeric_limits<uint64_t>::max(), 0);
return t;
}
@ -155,130 +158,139 @@ namespace windowfunction
template<typename T>
boost::shared_ptr<WindowFunctionType> WF_sum_avg<T>::makeFunction(int id, const string& name, int ct)
{
boost::shared_ptr<WindowFunctionType> func;
switch (ct)
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
{
func.reset(new WF_sum_avg<int64_t>(id, name));
break;
}
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UDECIMAL:
{
func.reset(new WF_sum_avg<uint64_t>(id, name));
break;
}
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
{
func.reset(new WF_sum_avg<double>(id, name));
break;
}
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
{
func.reset(new WF_sum_avg<float>(id, name));
break;
}
default:
{
string errStr = name + "(" + colType2String[ct] + ")";
errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_INVALID_PARM_TYPE, errStr);
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_INVALID_PARM_TYPE);
boost::shared_ptr<WindowFunctionType> func;
break;
}
}
switch (ct)
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
{
func.reset(new WF_sum_avg<int64_t>(id, name));
break;
}
return func;
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UDECIMAL:
{
func.reset(new WF_sum_avg<uint64_t>(id, name));
break;
}
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
{
func.reset(new WF_sum_avg<double>(id, name));
break;
}
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
{
func.reset(new WF_sum_avg<float>(id, name));
break;
}
default:
{
string errStr = name + "(" + colType2String[ct] + ")";
errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_INVALID_PARM_TYPE, errStr);
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_INVALID_PARM_TYPE);
break;
}
}
return func;
}
template<typename T>
WindowFunctionType* WF_sum_avg<T>::clone() const
{
return new WF_sum_avg<T>(*this);
return new WF_sum_avg<T>(*this);
}
template<typename T>
void WF_sum_avg<T>::resetData()
{
fAvg = 0;
fSum = 0;
fCount = 0;
fSet.clear();
fAvg = 0;
fSum = 0;
fCount = 0;
fSet.clear();
WindowFunctionType::resetData();
WindowFunctionType::resetData();
}
template<typename T>
void WF_sum_avg<T>::operator()(int64_t b, int64_t e, int64_t c)
{
uint64_t colOut = fFieldIndex[0];
uint64_t colOut = fFieldIndex[0];
if ((fFrameUnit == WF__FRAME_ROWS) ||
(fPrev == -1) ||
(!fPeer->operator()(getPointer(fRowData->at(c)), getPointer(fRowData->at(fPrev)))))
{
// for unbounded - current row special handling
if (fPrev >= b && fPrev < c)
b = c;
else if (fPrev <= e && fPrev > c)
e = c;
if ((fFrameUnit == WF__FRAME_ROWS) ||
(fPrev == -1) ||
(!fPeer->operator()(getPointer(fRowData->at(c)), getPointer(fRowData->at(fPrev)))))
{
// for unbounded - current row special handling
if (fPrev >= b && fPrev < c)
b = c;
else if (fPrev <= e && fPrev > c)
e = c;
uint64_t colIn = fFieldIndex[1];
int scale = fRow.getScale(colOut) - fRow.getScale(colIn);
for (int64_t i = b; i <= e; i++)
{
if (i % 1000 == 0 && fStep->cancelled())
break;
uint64_t colIn = fFieldIndex[1];
int scale = fRow.getScale(colOut) - fRow.getScale(colIn);
fRow.setData(getPointer(fRowData->at(i)));
if (fRow.isNullValue(colIn) == true)
continue;
for (int64_t i = b; i <= e; i++)
{
if (i % 1000 == 0 && fStep->cancelled())
break;
T valIn;
getValue(colIn, valIn);
checkSumLimit(fSum, valIn);
fRow.setData(getPointer(fRowData->at(i)));
if ((!fDistinct) || (fSet.find(valIn) == fSet.end()))
{
fSum += valIn;
fCount++;
if (fRow.isNullValue(colIn) == true)
continue;
if (fDistinct)
fSet.insert(valIn);
}
}
T valIn;
getValue(colIn, valIn);
checkSumLimit(fSum, valIn);
if ((fCount > 0) && (fFunctionId == WF__AVG || fFunctionId == WF__AVG_DISTINCT))
fAvg = (T) calculateAvg(fSum, fCount, scale);
}
if ((!fDistinct) || (fSet.find(valIn) == fSet.end()))
{
fSum += valIn;
fCount++;
T* v = NULL;
if (fCount > 0)
{
if (fFunctionId == WF__AVG || fFunctionId == WF__AVG_DISTINCT)
v = &fAvg;
else
v = &fSum;
}
setValue(fRow.getColType(colOut), b, e, c, v);
if (fDistinct)
fSet.insert(valIn);
}
}
fPrev = c;
if ((fCount > 0) && (fFunctionId == WF__AVG || fFunctionId == WF__AVG_DISTINCT))
fAvg = (T) calculateAvg(fSum, fCount, scale);
}
T* v = NULL;
if (fCount > 0)
{
if (fFunctionId == WF__AVG || fFunctionId == WF__AVG_DISTINCT)
v = &fAvg;
else
v = &fSum;
}
setValue(fRow.getColType(colOut), b, e, c, v);
fPrev = c;
}

View File

@ -33,22 +33,25 @@ template<typename T>
class WF_sum_avg : public WindowFunctionType
{
public:
WF_sum_avg(int id, const std::string& name) :
WindowFunctionType(id, name), fDistinct(id != WF__SUM && id != WF__AVG) {resetData();}
WF_sum_avg(int id, const std::string& name) :
WindowFunctionType(id, name), fDistinct(id != WF__SUM && id != WF__AVG)
{
resetData();
}
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
static boost::shared_ptr<WindowFunctionType> makeFunction(int, const string&, int);
static boost::shared_ptr<WindowFunctionType> makeFunction(int, const string&, int);
protected:
T fAvg;
T fSum;
uint64_t fCount;
bool fDistinct;
std::set<T> fSet;
T fAvg;
T fSum;
uint64_t fCount;
bool fDistinct;
std::set<T> fSet;
};

766
utils/windowfunction/wf_udaf.cpp Executable file → Normal file
View File

@ -55,448 +55,470 @@ namespace windowfunction
template<typename T>
boost::shared_ptr<WindowFunctionType> WF_udaf<T>::makeFunction(int id, const string& name, int ct, mcsv1sdk::mcsv1Context& context)
{
boost::shared_ptr<WindowFunctionType> func;
switch (ct)
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
{
func.reset(new WF_udaf<int64_t>(id, name, context));
break;
}
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UDECIMAL:
{
func.reset(new WF_udaf<uint64_t>(id, name, context));
break;
}
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
{
func.reset(new WF_udaf<double>(id, name, context));
break;
}
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
{
func.reset(new WF_udaf<float>(id, name, context));
break;
}
case CalpontSystemCatalog::CHAR:
case CalpontSystemCatalog::VARCHAR:
case CalpontSystemCatalog::VARBINARY:
case CalpontSystemCatalog::TEXT:
case CalpontSystemCatalog::BLOB:
{
func.reset(new WF_udaf<string>(id, name, context));
break;
}
default:
{
string errStr = name + "(" + colType2String[ct] + ")";
errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_INVALID_PARM_TYPE, errStr);
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_INVALID_PARM_TYPE);
boost::shared_ptr<WindowFunctionType> func;
break;
}
}
switch (ct)
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
{
func.reset(new WF_udaf<int64_t>(id, name, context));
break;
}
// Get the UDAnF function object
WF_udaf* wfUDAF = (WF_udaf*)func.get();
mcsv1sdk::mcsv1Context& udafContext = wfUDAF->getContext();
udafContext.setInterrupted(wfUDAF->getInterruptedPtr());
wfUDAF->resetData();
return func;
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UDECIMAL:
{
func.reset(new WF_udaf<uint64_t>(id, name, context));
break;
}
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
{
func.reset(new WF_udaf<double>(id, name, context));
break;
}
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
{
func.reset(new WF_udaf<float>(id, name, context));
break;
}
case CalpontSystemCatalog::CHAR:
case CalpontSystemCatalog::VARCHAR:
case CalpontSystemCatalog::VARBINARY:
case CalpontSystemCatalog::TEXT:
case CalpontSystemCatalog::BLOB:
{
func.reset(new WF_udaf<string>(id, name, context));
break;
}
default:
{
string errStr = name + "(" + colType2String[ct] + ")";
errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_INVALID_PARM_TYPE, errStr);
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_INVALID_PARM_TYPE);
break;
}
}
// Get the UDAnF function object
WF_udaf* wfUDAF = (WF_udaf*)func.get();
mcsv1sdk::mcsv1Context& udafContext = wfUDAF->getContext();
udafContext.setInterrupted(wfUDAF->getInterruptedPtr());
wfUDAF->resetData();
return func;
}
template<typename T>
WF_udaf<T>::WF_udaf(WF_udaf& rhs) : fUDAFContext(rhs.getContext()),
bInterrupted(rhs.getInterrupted()),
fDistinct(rhs.getDistinct())
bInterrupted(rhs.getInterrupted()),
fDistinct(rhs.getDistinct())
{
getContext().setInterrupted(getInterruptedPtr());
getContext().setInterrupted(getInterruptedPtr());
}
template<typename T>
WindowFunctionType* WF_udaf<T>::clone() const
{
return new WF_udaf(*const_cast<WF_udaf*>(this));
return new WF_udaf(*const_cast<WF_udaf*>(this));
}
template<typename T>
void WF_udaf<T>::resetData()
{
getContext().getFunction()->reset(&getContext());
fSet.clear();
WindowFunctionType::resetData();
getContext().getFunction()->reset(&getContext());
fSet.clear();
WindowFunctionType::resetData();
}
template<typename T>
void WF_udaf<T>::parseParms(const std::vector<execplan::SRCP>& parms)
{
bRespectNulls = true;
// parms[1]: respect null | ignore null
ConstantColumn* cc = dynamic_cast<ConstantColumn*>(parms[1].get());
idbassert(cc != NULL);
bool isNull = false; // dummy, harded coded
bRespectNulls = (cc->getIntVal(fRow, isNull) > 0);
// parms[1]: respect null | ignore null
ConstantColumn* cc = dynamic_cast<ConstantColumn*>(parms[1].get());
idbassert(cc != NULL);
bool isNull = false; // dummy, harded coded
bRespectNulls = (cc->getIntVal(fRow, isNull) > 0);
}
template<typename T>
bool WF_udaf<T>::dropValues(int64_t b, int64_t e)
{
if (!bHasDropValue)
{
// Save work if we discovered dropValue is not implemented in the UDAnF
return false;
}
if (!bHasDropValue)
{
// Save work if we discovered dropValue is not implemented in the UDAnF
return false;
}
mcsv1sdk::mcsv1_UDAF::ReturnCode rc;
uint64_t colOut = fFieldIndex[0];
uint64_t colIn = fFieldIndex[1];
mcsv1sdk::mcsv1_UDAF::ReturnCode rc;
uint64_t colOut = fFieldIndex[0];
uint64_t colIn = fFieldIndex[1];
mcsv1sdk::ColumnDatum datum;
datum.dataType = fRow.getColType(colIn);
datum.scale = fRow.getScale(colIn);
datum.precision = fRow.getPrecision(colOut);
mcsv1sdk::ColumnDatum datum;
datum.dataType = fRow.getColType(colIn);
datum.scale = fRow.getScale(colIn);
datum.precision = fRow.getPrecision(colOut);
for (int64_t i = b; i < e; i++)
{
if (i % 1000 == 0 && fStep->cancelled())
break;
for (int64_t i = b; i < e; i++)
{
if (i % 1000 == 0 && fStep->cancelled())
break;
fRow.setData(getPointer(fRowData->at(i)));
// Turn on NULL flags
std::vector<uint32_t> flags;
uint32_t flag = 0;
if (fRow.isNullValue(colIn) == true)
{
if (!bRespectNulls)
{
continue;
}
flag |= mcsv1sdk::PARAM_IS_NULL;
}
flags.push_back(flag);
getContext().setDataFlags(&flags);
fRow.setData(getPointer(fRowData->at(i)));
// Turn on NULL flags
std::vector<uint32_t> flags;
uint32_t flag = 0;
T valIn;
getValue(colIn, valIn, &datum.dataType);
if (fRow.isNullValue(colIn) == true)
{
if (!bRespectNulls)
{
continue;
}
// Check for distinct, if turned on.
// TODO: when we impliment distinct, we need to revist this.
if ((fDistinct) || (fSet.find(valIn) != fSet.end()))
{
continue;
}
flag |= mcsv1sdk::PARAM_IS_NULL;
}
datum.columnData = valIn;
flags.push_back(flag);
getContext().setDataFlags(&flags);
std::vector<mcsv1sdk::ColumnDatum> valsIn;
valsIn.push_back(datum);
T valIn;
getValue(colIn, valIn, &datum.dataType);
rc = getContext().getFunction()->dropValue(&getContext(), valsIn);
if (rc == mcsv1sdk::mcsv1_UDAF::NOT_IMPLEMENTED)
{
bHasDropValue = false;
return false;
}
if (rc == mcsv1sdk::mcsv1_UDAF::ERROR)
{
bInterrupted = true;
string errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_UDANF_ERROR, getContext().getErrorMessage());
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_UDANF_ERROR);
}
}
// Check for distinct, if turned on.
// TODO: when we impliment distinct, we need to revist this.
if ((fDistinct) || (fSet.find(valIn) != fSet.end()))
{
continue;
}
return true;
datum.columnData = valIn;
std::vector<mcsv1sdk::ColumnDatum> valsIn;
valsIn.push_back(datum);
rc = getContext().getFunction()->dropValue(&getContext(), valsIn);
if (rc == mcsv1sdk::mcsv1_UDAF::NOT_IMPLEMENTED)
{
bHasDropValue = false;
return false;
}
if (rc == mcsv1sdk::mcsv1_UDAF::ERROR)
{
bInterrupted = true;
string errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_UDANF_ERROR, getContext().getErrorMessage());
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_UDANF_ERROR);
}
}
return true;
}
// Sets the value from valOut into column colOut, performing any conversions.
template<typename T>
void WF_udaf<T>::SetUDAFValue(static_any::any& valOut, int64_t colOut,
int64_t b, int64_t e, int64_t c)
int64_t b, int64_t e, int64_t c)
{
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;
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;
CDT colDataType = fRow.getColType(colOut);
if (valOut.empty())
{
// If valOut is empty, we return NULL
T* pv = NULL;
setValue(colDataType, b, e, c, pv);
fPrev = c;
return;
}
CDT colDataType = fRow.getColType(colOut);
// 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.empty())
{
// If valOut is empty, we return NULL
T* pv = NULL;
setValue(colDataType, b, e, c, pv);
fPrev = c;
return;
}
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;
}
// 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(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();
}
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;
}
switch (colDataType)
{
case execplan::CalpontSystemCatalog::BIT:
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:
setValue(colDataType, b, e, c, &intOut);
break;
case execplan::CalpontSystemCatalog::UTINYINT:
case execplan::CalpontSystemCatalog::USMALLINT:
case execplan::CalpontSystemCatalog::UMEDINT:
case execplan::CalpontSystemCatalog::UINT:
case execplan::CalpontSystemCatalog::UBIGINT:
case execplan::CalpontSystemCatalog::DATE:
case execplan::CalpontSystemCatalog::DATETIME:
setValue(colDataType, b, e, c, &uintOut);
break;
case execplan::CalpontSystemCatalog::FLOAT:
case execplan::CalpontSystemCatalog::UFLOAT:
setValue(colDataType, b, e, c, &floatOut);
break;
case execplan::CalpontSystemCatalog::DOUBLE:
case execplan::CalpontSystemCatalog::UDOUBLE:
setValue(colDataType, b, e, c, &doubleOut);
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:
setValue(colDataType, b, e, c, &strOut);
break;
default:
{
std::ostringstream errmsg;
errmsg << "WF_udaf: No logic for data type: " << colDataType;
cerr << errmsg.str() << endl;
throw runtime_error(errmsg.str().c_str());
break;
}
}
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:
case execplan::CalpontSystemCatalog::SMALLINT:
case execplan::CalpontSystemCatalog::MEDINT:
case execplan::CalpontSystemCatalog::INT:
case execplan::CalpontSystemCatalog::BIGINT:
case execplan::CalpontSystemCatalog::DECIMAL:
case execplan::CalpontSystemCatalog::UDECIMAL:
setValue(colDataType, b, e, c, &intOut);
break;
case execplan::CalpontSystemCatalog::UTINYINT:
case execplan::CalpontSystemCatalog::USMALLINT:
case execplan::CalpontSystemCatalog::UMEDINT:
case execplan::CalpontSystemCatalog::UINT:
case execplan::CalpontSystemCatalog::UBIGINT:
case execplan::CalpontSystemCatalog::DATE:
case execplan::CalpontSystemCatalog::DATETIME:
setValue(colDataType, b, e, c, &uintOut);
break;
case execplan::CalpontSystemCatalog::FLOAT:
case execplan::CalpontSystemCatalog::UFLOAT:
setValue(colDataType, b, e, c, &floatOut);
break;
case execplan::CalpontSystemCatalog::DOUBLE:
case execplan::CalpontSystemCatalog::UDOUBLE:
setValue(colDataType, b, e, c, &doubleOut);
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:
setValue(colDataType, b, e, c, &strOut);
break;
default:
{
std::ostringstream errmsg;
errmsg << "WF_udaf: No logic for data type: " << colDataType;
cerr << errmsg.str() << endl;
throw runtime_error(errmsg.str().c_str());
break;
}
}
}
template<typename T>
void WF_udaf<T>::operator()(int64_t b, int64_t e, int64_t c)
{
mcsv1sdk::mcsv1_UDAF::ReturnCode rc;
uint64_t colOut = fFieldIndex[0];
mcsv1sdk::mcsv1_UDAF::ReturnCode rc;
uint64_t colOut = fFieldIndex[0];
if ((fFrameUnit == WF__FRAME_ROWS) ||
(fPrev == -1) ||
(!fPeer->operator()(getPointer(fRowData->at(c)), getPointer(fRowData->at(fPrev)))))
{
// for unbounded - current row special handling
if (fPrev >= b && fPrev < c)
b = c;
else if (fPrev <= e && fPrev > c)
e = c;
if ((fFrameUnit == WF__FRAME_ROWS) ||
(fPrev == -1) ||
(!fPeer->operator()(getPointer(fRowData->at(c)), getPointer(fRowData->at(fPrev)))))
{
// for unbounded - current row special handling
if (fPrev >= b && fPrev < c)
b = c;
else if (fPrev <= e && fPrev > c)
e = c;
uint64_t colIn = fFieldIndex[1];
uint64_t colIn = fFieldIndex[1];
mcsv1sdk::ColumnDatum datum;
datum.dataType = fRow.getColType(colIn);
datum.scale = fRow.getScale(colIn);
datum.precision = fRow.getPrecision(colOut);
mcsv1sdk::ColumnDatum datum;
datum.dataType = fRow.getColType(colIn);
datum.scale = fRow.getScale(colIn);
datum.precision = fRow.getPrecision(colOut);
if (b<=c && c<=e)
getContext().setContextFlag(mcsv1sdk::CONTEXT_HAS_CURRENT_ROW);
else
getContext().clearContextFlag(mcsv1sdk::CONTEXT_HAS_CURRENT_ROW);
if (b <= c && c <= e)
getContext().setContextFlag(mcsv1sdk::CONTEXT_HAS_CURRENT_ROW);
else
getContext().clearContextFlag(mcsv1sdk::CONTEXT_HAS_CURRENT_ROW);
for (int64_t i = b; i <= e; i++)
{
if (i % 1000 == 0 && fStep->cancelled())
break;
for (int64_t i = b; i <= e; i++)
{
if (i % 1000 == 0 && fStep->cancelled())
break;
fRow.setData(getPointer(fRowData->at(i)));
// Turn on NULL flags
std::vector<uint32_t> flags;
uint32_t flag = 0;
if (fRow.isNullValue(colIn) == true)
{
if (!bRespectNulls)
{
continue;
}
flag |= mcsv1sdk::PARAM_IS_NULL;
}
flags.push_back(flag);
getContext().setDataFlags(&flags);
fRow.setData(getPointer(fRowData->at(i)));
// Turn on NULL flags
std::vector<uint32_t> flags;
uint32_t flag = 0;
T valIn;
getValue(colIn, valIn, &datum.dataType);
if (fRow.isNullValue(colIn) == true)
{
if (!bRespectNulls)
{
continue;
}
// Check for distinct, if turned on.
if ((fDistinct) || (fSet.find(valIn) != fSet.end()))
{
continue;
}
flag |= mcsv1sdk::PARAM_IS_NULL;
}
if (fDistinct)
fSet.insert(valIn);
flags.push_back(flag);
getContext().setDataFlags(&flags);
datum.columnData = valIn;
T valIn;
getValue(colIn, valIn, &datum.dataType);
std::vector<mcsv1sdk::ColumnDatum> valsIn;
valsIn.push_back(datum);
// Check for distinct, if turned on.
if ((fDistinct) || (fSet.find(valIn) != fSet.end()))
{
continue;
}
rc = getContext().getFunction()->nextValue(&getContext(), valsIn);
if (rc == mcsv1sdk::mcsv1_UDAF::ERROR)
{
bInterrupted = true;
string errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_UDANF_ERROR, getContext().getErrorMessage());
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_UDANF_ERROR);
}
}
if (fDistinct)
fSet.insert(valIn);
rc = getContext().getFunction()->evaluate(&getContext(), fValOut);
if (rc == mcsv1sdk::mcsv1_UDAF::ERROR)
{
bInterrupted = true;
string errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_UDANF_ERROR, getContext().getErrorMessage());
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_UDANF_ERROR);
}
}
datum.columnData = valIn;
SetUDAFValue(fValOut, colOut, b, e, c);
std::vector<mcsv1sdk::ColumnDatum> valsIn;
valsIn.push_back(datum);
fPrev = c;
rc = getContext().getFunction()->nextValue(&getContext(), valsIn);
if (rc == mcsv1sdk::mcsv1_UDAF::ERROR)
{
bInterrupted = true;
string errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_UDANF_ERROR, getContext().getErrorMessage());
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_UDANF_ERROR);
}
}
rc = getContext().getFunction()->evaluate(&getContext(), fValOut);
if (rc == mcsv1sdk::mcsv1_UDAF::ERROR)
{
bInterrupted = true;
string errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_UDANF_ERROR, getContext().getErrorMessage());
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_UDANF_ERROR);
}
}
SetUDAFValue(fValOut, colOut, b, e, c);
fPrev = c;
}
template

58
utils/windowfunction/wf_udaf.h Executable file → Normal file
View File

@ -37,35 +37,47 @@ template<typename T>
class WF_udaf : public WindowFunctionType
{
public:
WF_udaf(int id, const std::string& name, mcsv1sdk::mcsv1Context& context) :
WindowFunctionType(id, name), fUDAFContext(context), fDistinct(false), bHasDropValue(true) {}
WF_udaf(WF_udaf& rhs);
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
void parseParms(const std::vector<execplan::SRCP>&);
virtual bool dropValues(int64_t, int64_t);
WF_udaf(int id, const std::string& name, mcsv1sdk::mcsv1Context& context) :
WindowFunctionType(id, name), fUDAFContext(context), fDistinct(false), bHasDropValue(true) {}
WF_udaf(WF_udaf& rhs);
// pure virtual in base
void operator()(int64_t b, int64_t e, int64_t c);
WindowFunctionType* clone() const;
void resetData();
void parseParms(const std::vector<execplan::SRCP>&);
virtual bool dropValues(int64_t, int64_t);
mcsv1sdk::mcsv1Context& getContext() {return fUDAFContext;}
bool getInterrupted() {return bInterrupted;}
bool getInterruptedPtr() {return &bInterrupted;}
bool getDistinct() {return fDistinct;}
mcsv1sdk::mcsv1Context& getContext()
{
return fUDAFContext;
}
bool getInterrupted()
{
return bInterrupted;
}
bool getInterruptedPtr()
{
return &bInterrupted;
}
bool getDistinct()
{
return fDistinct;
}
protected:
void SetUDAFValue(static_any::any& valOut, int64_t colOut, int64_t b, int64_t e, int64_t c);
void SetUDAFValue(static_any::any& valOut, int64_t colOut, int64_t b, int64_t e, int64_t c);
mcsv1sdk::mcsv1Context fUDAFContext; // The UDAF context
bool bInterrupted; // Shared by all the threads
bool fDistinct;
bool bRespectNulls; // respect null | ignore null
bool bHasDropValue; // Set to false when we discover the UDAnF doesn't implement dropValue.
std::set<T> fSet; // To hold distinct values
static_any::any fValOut; // The return value
mcsv1sdk::mcsv1Context fUDAFContext; // The UDAF context
bool bInterrupted; // Shared by all the threads
bool fDistinct;
bool bRespectNulls; // respect null | ignore null
bool bHasDropValue; // Set to false when we discover the UDAnF doesn't implement dropValue.
std::set<T> fSet; // To hold distinct values
static_any::any fValOut; // The return value
public:
static boost::shared_ptr<WindowFunctionType> makeFunction(int id, const string& name,
int ct, mcsv1sdk::mcsv1Context& context);
static boost::shared_ptr<WindowFunctionType> makeFunction(int id, const string& name,
int ct, mcsv1sdk::mcsv1Context& context);
};

View File

@ -1,4 +1,4 @@
/*
/*
Copyright (c) 2017, MariaDB
Copyright (C) 2014 InfiniDB, Inc.
@ -53,37 +53,37 @@ namespace windowfunction
pair<uint64_t, uint64_t> WindowFrame::getWindow(int64_t b, int64_t e, int64_t c)
{
int64_t upper = fUpper->getBound(b, e, c);
int64_t lower = fLower->getBound(b, e, c);
int64_t upper = fUpper->getBound(b, e, c);
int64_t lower = fLower->getBound(b, e, c);
// case 1 || case 2 || case 3
if ((upper > lower) || (upper < b && lower < b) || (upper > e && lower > e))
{
// construct an empty window
upper = b+1;
lower = b;
}
// case 1 || case 2 || case 3
if ((upper > lower) || (upper < b && lower < b) || (upper > e && lower > e))
{
// construct an empty window
upper = b + 1;
lower = b;
}
if (upper < b) // case 2, lower >= b
{
upper = b;
}
if (upper < b) // case 2, lower >= b
{
upper = b;
}
if (lower > e) // case 3, upper <= e
{
lower = e;
}
if (lower > e) // case 3, upper <= e
{
lower = e;
}
return make_pair(upper, lower);
return make_pair(upper, lower);
}
const string WindowFrame::toString() const
{
string ret(UnitStr[fUnit]);
ret = ret + " between " + fUpper->toString() + " and " + fLower->toString();
string ret(UnitStr[fUnit]);
ret = ret + " between " + fUpper->toString() + " and " + fLower->toString();
return ret;
return ret;
}
} //namespace

View File

@ -38,58 +38,88 @@ const int64_t WF__FRAME_RANGE = 1;
class WindowFrame
{
public:
/** @brief WindowFrame constructor
*/
WindowFrame(int64_t t, boost::shared_ptr<FrameBound>& u, boost::shared_ptr<FrameBound>& l) :
fUnit(t), fUpper(u), fLower(l)
{}
/** @brief WindowFrame constructor
*/
WindowFrame(int64_t t, boost::shared_ptr<FrameBound>& u, boost::shared_ptr<FrameBound>& l) :
fUnit(t), fUpper(u), fLower(l)
{}
/** @brief WindowFrame copy constructor
*/
WindowFrame(const WindowFrame& rhs) :
fUnit(rhs.fUnit),
fUpper(rhs.fUpper->clone()),
fLower(rhs.fLower->clone())
{}
/** @brief WindowFrame copy constructor
*/
WindowFrame(const WindowFrame& rhs) :
fUnit(rhs.fUnit),
fUpper(rhs.fUpper->clone()),
fLower(rhs.fLower->clone())
{}
/** @brief WindowFrame destructor
*/
virtual ~WindowFrame() {};
/** @brief WindowFrame destructor
*/
virtual ~WindowFrame() {};
/** @brief clone
*/
virtual WindowFrame* clone() { return new WindowFrame(*this); };
/** @brief clone
*/
virtual WindowFrame* clone()
{
return new WindowFrame(*this);
};
/** @brief virtual void getWindow
*/
std::pair<uint64_t, uint64_t> getWindow(int64_t, int64_t, int64_t);
/** @brief virtual void getWindow
*/
std::pair<uint64_t, uint64_t> getWindow(int64_t, int64_t, int64_t);
const std::string toString() const;
const std::string toString() const;
/** @brief set methods
*/
void setRowMetaData(const rowgroup::RowGroup& g, const rowgroup::Row& r)
{ fUpper->setRowMetaData(g, r); fLower->setRowMetaData(g, r); }
void setRowData(boost::shared_ptr<std::vector<joblist::RowPosition> >& d)
{ fUpper->setRowData(d); fLower->setRowData(d); }
void setCallback(joblist::WindowFunctionStep* s)
{ fUpper->setCallback(s); fLower->setCallback(s); }
/** @brief set methods
*/
void setRowMetaData(const rowgroup::RowGroup& g, const rowgroup::Row& r)
{
fUpper->setRowMetaData(g, r);
fLower->setRowMetaData(g, r);
}
void setRowData(boost::shared_ptr<std::vector<joblist::RowPosition> >& d)
{
fUpper->setRowData(d);
fLower->setRowData(d);
}
void setCallback(joblist::WindowFunctionStep* s)
{
fUpper->setCallback(s);
fLower->setCallback(s);
}
int64_t unit() const { return fUnit; }
void unit(int64_t t) { fUnit = t; }
const boost::shared_ptr<FrameBound>& upper() const { return fUpper; }
void upper(const boost::shared_ptr<FrameBound>& u) { fUpper = u; }
const boost::shared_ptr<FrameBound>& lower() const { return fLower; }
void lower(const boost::shared_ptr<FrameBound>& l) { fLower = l; }
int64_t unit() const
{
return fUnit;
}
void unit(int64_t t)
{
fUnit = t;
}
const boost::shared_ptr<FrameBound>& upper() const
{
return fUpper;
}
void upper(const boost::shared_ptr<FrameBound>& u)
{
fUpper = u;
}
const boost::shared_ptr<FrameBound>& lower() const
{
return fLower;
}
void lower(const boost::shared_ptr<FrameBound>& l)
{
fLower = l;
}
protected:
// type
int64_t fUnit;
// type
int64_t fUnit;
// data
boost::shared_ptr<FrameBound> fUpper;
boost::shared_ptr<FrameBound> fLower;
// data
boost::shared_ptr<FrameBound> fUpper;
boost::shared_ptr<FrameBound> fLower;
};

349
utils/windowfunction/windowfunction.cpp Executable file → Normal file
View File

@ -1,4 +1,4 @@
/*
/*
Copyright (c) 2017, MariaDB
Copyright (C) 2014 InfiniDB, Inc.
@ -56,7 +56,7 @@ WindowFunction::WindowFunction(boost::shared_ptr<WindowFunctionType>& f,
boost::shared_ptr<WindowFrame>& w,
const RowGroup& g,
const Row& r) :
fFunctionType(f), fPartitionBy(p), fOrderBy(o), fFrame(w), fRowGroup(g), fRow(r)
fFunctionType(f), fPartitionBy(p), fOrderBy(o), fFrame(w), fRowGroup(g), fRow(r)
{
}
@ -68,194 +68,207 @@ WindowFunction::~WindowFunction()
void WindowFunction::operator()()
{
try
{
fRowData.reset(new vector<RowPosition>(fStep->getRowData()));
try
{
fRowData.reset(new vector<RowPosition>(fStep->getRowData()));
if (fOrderBy->rule().fCompares.size() > 0)
sort(fRowData->begin(), fRowData->size());
if (fOrderBy->rule().fCompares.size() > 0)
sort(fRowData->begin(), fRowData->size());
// get partitions
if (fPartitionBy.get() != NULL && !fStep->cancelled())
{
int64_t i = 0;
int64_t j = 1;
int64_t rowCnt = fRowData->size();
for (j = 1; j < rowCnt; j++)
{
if ((*(fPartitionBy.get()))
(getPointer((*fRowData)[j-1]), getPointer((*fRowData)[j])))
continue;
// get partitions
if (fPartitionBy.get() != NULL && !fStep->cancelled())
{
int64_t i = 0;
int64_t j = 1;
int64_t rowCnt = fRowData->size();
fPartition.push_back(make_pair(i, j-1));
i = j;
}
fPartition.push_back(make_pair(i, j-1));
}
else
{
fPartition.push_back(make_pair(0, fRowData->size()));
}
for (j = 1; j < rowCnt; j++)
{
if ((*(fPartitionBy.get()))
(getPointer((*fRowData)[j - 1]), getPointer((*fRowData)[j])))
continue;
// compute partition by partition
int64_t uft = fFrame->upper()->boundType();
int64_t lft = fFrame->lower()->boundType();
bool upperUbnd = (uft == WF__UNBOUNDED_PRECEDING || uft == WF__UNBOUNDED_FOLLOWING);
bool lowerUbnd = (lft == WF__UNBOUNDED_PRECEDING || lft == WF__UNBOUNDED_FOLLOWING);
bool upperCnrw = (uft == WF__CURRENT_ROW);
bool lowerCnrw = (lft == WF__CURRENT_ROW);
fFunctionType->setRowData(fRowData);
fFunctionType->setRowMetaData(fRowGroup,fRow);
fFrame->setRowData(fRowData);
fFrame->setRowMetaData(fRowGroup, fRow);
for (uint64_t k = 0; k < fPartition.size() && !fStep->cancelled(); k++)
{
fFunctionType->resetData();
fFunctionType->partition(fPartition[k]);
fPartition.push_back(make_pair(i, j - 1));
i = j;
}
int64_t begin = fPartition[k].first;
int64_t end = fPartition[k].second;
if (upperUbnd && lowerUbnd)
{
fFunctionType->operator()(begin, end, WF__BOUND_ALL);
}
else if (upperUbnd && lowerCnrw)
{
if (fFrame->unit() == WF__FRAME_ROWS)
{
for (int64_t i = begin; i <= end && !fStep->cancelled(); i++)
{
fFunctionType->operator()(begin, i, i);
}
}
else
{
for (int64_t i = begin; i <= end && !fStep->cancelled(); i++)
{
pair<int64_t, int64_t> w = fFrame->getWindow(begin, end, i);
int64_t j = i;
if (w.second > i)
j = w.second;
fFunctionType->operator()(begin, j, i);
}
}
}
else if (upperCnrw && lowerUbnd)
{
if (fFrame->unit() == WF__FRAME_ROWS)
{
for (int64_t i = end; i >= begin && !fStep->cancelled(); i--)
{
fFunctionType->operator()(i, end, i);
}
}
else
{
for (int64_t i = end; i >= begin && !fStep->cancelled(); i--)
{
pair<int64_t, int64_t> w = fFrame->getWindow(begin, end, i);
int64_t j = i;
if (w.first < i)
j = w.first;
fFunctionType->operator()(j, end, i);
}
}
}
else
{
pair<int64_t, int64_t> w;
pair<int64_t, int64_t> prevFrame;
int64_t b, e;
bool firstTime = true;
for (int64_t i = begin; i <= end && !fStep->cancelled(); i++)
{
w = fFrame->getWindow(begin, end, i);
b = w.first;
e = w.second;
if (firstTime)
{
prevFrame = w;
}
// UDAnF functions may have a dropValue function implemented.
// If they do, we can optimize by calling dropValue() for those
// values leaving the window and nextValue for those entering, rather
// than a resetData() and then iterating over the entire window.
// Built-in functions may have this functionality added in the future.
if (fFunctionType->dropValues(prevFrame.first, w.first))
{
b = firstTime ? w.first : prevFrame.second+1;
}
else
{
fFunctionType->resetData();
}
fFunctionType->operator()(b, e, i);
prevFrame = w;
firstTime = false;
}
}
}
}
catch (IDBExcept& iex)
{
fStep->handleException(iex.what(), iex.errorCode());
}
catch(const std::exception& ex)
{
fStep->handleException(ex.what(), logging::ERR_EXECUTE_WINDOW_FUNCTION);
}
catch(...)
{
fStep->handleException("unknow exception", logging::ERR_EXECUTE_WINDOW_FUNCTION);
}
fPartition.push_back(make_pair(i, j - 1));
}
else
{
fPartition.push_back(make_pair(0, fRowData->size()));
}
// compute partition by partition
int64_t uft = fFrame->upper()->boundType();
int64_t lft = fFrame->lower()->boundType();
bool upperUbnd = (uft == WF__UNBOUNDED_PRECEDING || uft == WF__UNBOUNDED_FOLLOWING);
bool lowerUbnd = (lft == WF__UNBOUNDED_PRECEDING || lft == WF__UNBOUNDED_FOLLOWING);
bool upperCnrw = (uft == WF__CURRENT_ROW);
bool lowerCnrw = (lft == WF__CURRENT_ROW);
fFunctionType->setRowData(fRowData);
fFunctionType->setRowMetaData(fRowGroup, fRow);
fFrame->setRowData(fRowData);
fFrame->setRowMetaData(fRowGroup, fRow);
for (uint64_t k = 0; k < fPartition.size() && !fStep->cancelled(); k++)
{
fFunctionType->resetData();
fFunctionType->partition(fPartition[k]);
int64_t begin = fPartition[k].first;
int64_t end = fPartition[k].second;
if (upperUbnd && lowerUbnd)
{
fFunctionType->operator()(begin, end, WF__BOUND_ALL);
}
else if (upperUbnd && lowerCnrw)
{
if (fFrame->unit() == WF__FRAME_ROWS)
{
for (int64_t i = begin; i <= end && !fStep->cancelled(); i++)
{
fFunctionType->operator()(begin, i, i);
}
}
else
{
for (int64_t i = begin; i <= end && !fStep->cancelled(); i++)
{
pair<int64_t, int64_t> w = fFrame->getWindow(begin, end, i);
int64_t j = i;
if (w.second > i)
j = w.second;
fFunctionType->operator()(begin, j, i);
}
}
}
else if (upperCnrw && lowerUbnd)
{
if (fFrame->unit() == WF__FRAME_ROWS)
{
for (int64_t i = end; i >= begin && !fStep->cancelled(); i--)
{
fFunctionType->operator()(i, end, i);
}
}
else
{
for (int64_t i = end; i >= begin && !fStep->cancelled(); i--)
{
pair<int64_t, int64_t> w = fFrame->getWindow(begin, end, i);
int64_t j = i;
if (w.first < i)
j = w.first;
fFunctionType->operator()(j, end, i);
}
}
}
else
{
pair<int64_t, int64_t> w;
pair<int64_t, int64_t> prevFrame;
int64_t b, e;
bool firstTime = true;
for (int64_t i = begin; i <= end && !fStep->cancelled(); i++)
{
w = fFrame->getWindow(begin, end, i);
b = w.first;
e = w.second;
if (firstTime)
{
prevFrame = w;
}
// UDAnF functions may have a dropValue function implemented.
// If they do, we can optimize by calling dropValue() for those
// values leaving the window and nextValue for those entering, rather
// than a resetData() and then iterating over the entire window.
// Built-in functions may have this functionality added in the future.
if (fFunctionType->dropValues(prevFrame.first, w.first))
{
b = firstTime ? w.first : prevFrame.second + 1;
}
else
{
fFunctionType->resetData();
}
fFunctionType->operator()(b, e, i);
prevFrame = w;
firstTime = false;
}
}
}
}
catch (IDBExcept& iex)
{
fStep->handleException(iex.what(), iex.errorCode());
}
catch (const std::exception& ex)
{
fStep->handleException(ex.what(), logging::ERR_EXECUTE_WINDOW_FUNCTION);
}
catch (...)
{
fStep->handleException("unknow exception", logging::ERR_EXECUTE_WINDOW_FUNCTION);
}
}
void WindowFunction::setCallback(joblist::WindowFunctionStep* step, int id)
{
fStep = step;
fId = id;
fFunctionType->setCallback(step);
fFrame->setCallback(step);
fStep = step;
fId = id;
fFunctionType->setCallback(step);
fFrame->setCallback(step);
}
const Row& WindowFunction::getRow() const
{
return fRow;
return fRow;
}
void WindowFunction::sort(std::vector<RowPosition>::iterator v, uint64_t n)
{
// recursive function termination condition.
if (n < 2 || fStep->cancelled())
return;
// recursive function termination condition.
if (n < 2 || fStep->cancelled())
return;
RowPosition p = *(v + n/2); // pivot value
vector<RowPosition>::iterator l = v; // low address
vector<RowPosition>::iterator h = v + (n - 1); // high address
while (l <= h && !(fStep->cancelled()))
{
// Can use while here, but need check boundary and cancel status.
if (fOrderBy->operator()(getPointer(*l), getPointer(p)))
{
l++;
}
else if (fOrderBy->operator()(getPointer(p), getPointer(*h)))
{
h--;
}
else
{
RowPosition t = *l; // temp value for swap
*l++ = *h;
*h-- = t;
}
}
RowPosition p = *(v + n / 2); // pivot value
vector<RowPosition>::iterator l = v; // low address
vector<RowPosition>::iterator h = v + (n - 1); // high address
sort(v, distance(v, h) + 1);
sort(l, distance(l, v) + n);
while (l <= h && !(fStep->cancelled()))
{
// Can use while here, but need check boundary and cancel status.
if (fOrderBy->operator()(getPointer(*l), getPointer(p)))
{
l++;
}
else if (fOrderBy->operator()(getPointer(p), getPointer(*h)))
{
h--;
}
else
{
RowPosition t = *l; // temp value for swap
*l++ = *h;
*h-- = t;
}
}
sort(v, distance(v, h) + 1);
sort(l, distance(l, v) + n);
}

View File

@ -51,70 +51,72 @@ class WindowFrame;
class WindowFunction
{
public:
/** @brief WindowFunction constructor
* @param f: shared pointer to a WindowFuncitonType
* @param p: shared pointer to equal compare functor
* @param o: shared pointer to order by functor
* @param w: shared pointer to window specification
* @param r: row meta data
*/
WindowFunction(boost::shared_ptr<WindowFunctionType>& f,
boost::shared_ptr<ordering::EqualCompData>& p,
boost::shared_ptr<ordering::OrderByData>& o,
boost::shared_ptr<WindowFrame>& w,
const rowgroup::RowGroup& g,
const rowgroup::Row& r);
/** @brief WindowFunction constructor
* @param f: shared pointer to a WindowFuncitonType
* @param p: shared pointer to equal compare functor
* @param o: shared pointer to order by functor
* @param w: shared pointer to window specification
* @param r: row meta data
*/
WindowFunction(boost::shared_ptr<WindowFunctionType>& f,
boost::shared_ptr<ordering::EqualCompData>& p,
boost::shared_ptr<ordering::OrderByData>& o,
boost::shared_ptr<WindowFrame>& w,
const rowgroup::RowGroup& g,
const rowgroup::Row& r);
/** @brief WindowFunction destructor
*/
virtual ~WindowFunction();
/** @brief WindowFunction destructor
*/
virtual ~WindowFunction();
/** @brief virtual void Run method
*/
void operator()();
/** @brief virtual void Run method
*/
void operator()();
const std::string toString() const;
const std::string toString() const;
void setCallback(joblist::WindowFunctionStep*, int);
const rowgroup::Row& getRow() const;
void setCallback(joblist::WindowFunctionStep*, int);
const rowgroup::Row& getRow() const;
protected:
// cancellable sort function
void sort(std::vector<joblist::RowPosition>::iterator, uint64_t);
// cancellable sort function
void sort(std::vector<joblist::RowPosition>::iterator, uint64_t);
// special window frames
void processUnboundedWindowFrame1();
void processUnboundedWindowFrame2();
void processUnboundedWindowFrame3();
void processExprWindowFrame();
// special window frames
void processUnboundedWindowFrame1();
void processUnboundedWindowFrame2();
void processUnboundedWindowFrame3();
void processExprWindowFrame();
// for string table
rowgroup::Row::Pointer getPointer(joblist::RowPosition& r)
{ return fStep->getPointer(r, fRowGroup, fRow); }
// for string table
rowgroup::Row::Pointer getPointer(joblist::RowPosition& r)
{
return fStep->getPointer(r, fRowGroup, fRow);
}
// function type
boost::shared_ptr<WindowFunctionType> fFunctionType;
// function type
boost::shared_ptr<WindowFunctionType> fFunctionType;
// window clause
boost::shared_ptr<ordering::EqualCompData> fPartitionBy;
boost::shared_ptr<ordering::OrderByData> fOrderBy;
boost::shared_ptr<WindowFrame> fFrame;
std::vector<std::pair<int64_t, int64_t> > fPartition;
// window clause
boost::shared_ptr<ordering::EqualCompData> fPartitionBy;
boost::shared_ptr<ordering::OrderByData> fOrderBy;
boost::shared_ptr<WindowFrame> fFrame;
std::vector<std::pair<int64_t, int64_t> > fPartition;
// data
boost::shared_ptr<std::vector<joblist::RowPosition> > fRowData;
// data
boost::shared_ptr<std::vector<joblist::RowPosition> > fRowData;
// row meta data
rowgroup::RowGroup fRowGroup;
rowgroup::Row fRow;
// row meta data
rowgroup::RowGroup fRowGroup;
rowgroup::Row fRow;
// pointer back to step
joblist::WindowFunctionStep* fStep;
int fId;
// pointer back to step
joblist::WindowFunctionStep* fStep;
int fId;
friend class joblist::WindowFunctionStep;
friend class joblist::WindowFunctionStep;
};

806
utils/windowfunction/windowfunctiontype.cpp Executable file → Normal file
View File

@ -1,4 +1,4 @@
/*
/*
Copyright (c) 2017, MariaDB
Copyright (C) 2014 InfiniDB, Inc.
@ -64,169 +64,183 @@ namespace windowfunction
{
map<int, string> colType2String = assign::map_list_of
(CalpontSystemCatalog::BIT, "BIT")
(CalpontSystemCatalog::TINYINT, "TINYINT")
(CalpontSystemCatalog::CHAR, "CHAR")
(CalpontSystemCatalog::SMALLINT, "SMALLINT")
(CalpontSystemCatalog::DECIMAL, "DECIMAL")
(CalpontSystemCatalog::MEDINT, "MEDINT")
(CalpontSystemCatalog::INT, "INT")
(CalpontSystemCatalog::FLOAT, "FLOAT")
(CalpontSystemCatalog::DATE, "DATE")
(CalpontSystemCatalog::BIGINT, "BIGINT")
(CalpontSystemCatalog::DOUBLE, "DOUBLE")
(CalpontSystemCatalog::DATETIME, "DATETIME")
(CalpontSystemCatalog::VARCHAR, "VARCHAR")
(CalpontSystemCatalog::VARBINARY, "VARBINARY")
(CalpontSystemCatalog::CLOB, "CLOB")
(CalpontSystemCatalog::BLOB, "BLOB")
(CalpontSystemCatalog::UTINYINT, "UNSIGNED TINYINT")
(CalpontSystemCatalog::USMALLINT, "UNSIGNED SMALLINT")
(CalpontSystemCatalog::UDECIMAL, "UNSIGNED DECIMAL")
(CalpontSystemCatalog::UMEDINT, "UNSIGNED MEDINT")
(CalpontSystemCatalog::UINT, "UNSIGNED INT")
(CalpontSystemCatalog::UFLOAT, "UNSIGNED FLOAT")
(CalpontSystemCatalog::UBIGINT, "UNSIGNED BIGINT")
(CalpontSystemCatalog::UDOUBLE, "UNSIGNED DOUBLE")
(CalpontSystemCatalog::LONGDOUBLE, "INTERNAL LONG DOUBLE")
(CalpontSystemCatalog::STRINT, "INTERNAL SHORT STRING")
(CalpontSystemCatalog::TEXT, "TEXT")
;
(CalpontSystemCatalog::BIT, "BIT")
(CalpontSystemCatalog::TINYINT, "TINYINT")
(CalpontSystemCatalog::CHAR, "CHAR")
(CalpontSystemCatalog::SMALLINT, "SMALLINT")
(CalpontSystemCatalog::DECIMAL, "DECIMAL")
(CalpontSystemCatalog::MEDINT, "MEDINT")
(CalpontSystemCatalog::INT, "INT")
(CalpontSystemCatalog::FLOAT, "FLOAT")
(CalpontSystemCatalog::DATE, "DATE")
(CalpontSystemCatalog::BIGINT, "BIGINT")
(CalpontSystemCatalog::DOUBLE, "DOUBLE")
(CalpontSystemCatalog::DATETIME, "DATETIME")
(CalpontSystemCatalog::VARCHAR, "VARCHAR")
(CalpontSystemCatalog::VARBINARY, "VARBINARY")
(CalpontSystemCatalog::CLOB, "CLOB")
(CalpontSystemCatalog::BLOB, "BLOB")
(CalpontSystemCatalog::UTINYINT, "UNSIGNED TINYINT")
(CalpontSystemCatalog::USMALLINT, "UNSIGNED SMALLINT")
(CalpontSystemCatalog::UDECIMAL, "UNSIGNED DECIMAL")
(CalpontSystemCatalog::UMEDINT, "UNSIGNED MEDINT")
(CalpontSystemCatalog::UINT, "UNSIGNED INT")
(CalpontSystemCatalog::UFLOAT, "UNSIGNED FLOAT")
(CalpontSystemCatalog::UBIGINT, "UNSIGNED BIGINT")
(CalpontSystemCatalog::UDOUBLE, "UNSIGNED DOUBLE")
(CalpontSystemCatalog::LONGDOUBLE, "INTERNAL LONG DOUBLE")
(CalpontSystemCatalog::STRINT, "INTERNAL SHORT STRING")
(CalpontSystemCatalog::TEXT, "TEXT")
;
// function name to function id convert
map<string, int> WindowFunctionType::windowFunctionId = assign::map_list_of
(string("COUNT(*)"), WF__COUNT_ASTERISK)
(string("COUNT"), WF__COUNT)
(string("SUM"), WF__SUM)
(string("AVG"), WF__AVG)
(string("MIN"), WF__MIN)
(string("MAX"), WF__MAX)
(string("COUNT_DISTINCT"), WF__COUNT_DISTINCT)
(string("SUM_DISTINCT"), WF__SUM_DISTINCT)
(string("AVG_DISTINCT"), WF__AVG_DISTINCT)
(string("MIN_DISTINCT"), WF__MIN)
(string("MAX_DISTINCT"), WF__MAX)
(string("STD"), WF__STDDEV_POP)
(string("STDDEV"), WF__STDDEV_POP)
(string("STDDEV_POP"), WF__STDDEV_POP)
(string("STDDEV_SAMP"), WF__STDDEV_SAMP)
(string("VARIANCE"), WF__VAR_POP)
(string("VAR_POP"), WF__VAR_POP)
(string("VAR_SAMP"), WF__VAR_SAMP)
(string("ROW_NUMBER"), WF__ROW_NUMBER)
(string("RANK"), WF__RANK)
(string("PERCENT_RANK"), WF__PERCENT_RANK)
(string("DENSE_RANK"), WF__DENSE_RANK)
(string("CUME_DIST"), WF__CUME_DIST)
(string("FIRST_VALUE"), WF__FIRST_VALUE)
(string("LAST_VALUE"), WF__LAST_VALUE)
(string("NTH_VALUE"), WF__NTH_VALUE)
(string("LAG"), WF__LAG)
(string("LEAD"), WF__LEAD)
(string("NTILE"), WF__NTILE)
(string("MEDIAN"), WF__PERCENTILE_CONT)
(string("PERCENTILE"), WF__PERCENTILE_CONT)
(string("PERCENTILE_CONT"), WF__PERCENTILE_CONT)
(string("PERCENTILE_DISC"), WF__PERCENTILE_DISC)
(string("REGR_SLOPE"), WF__REGR_SLOPE)
(string("REGR_INTERCEPT"), WF__REGR_INTERCEPT)
(string("REGR_COUNT"), WF__REGR_COUNT)
(string("REGR_R2"), WF__REGR_R2)
(string("REGR_AVGX"), WF__REGR_AVGX)
(string("REGR_AVGY"), WF__REGR_AVGY)
(string("REGR_SXX"), WF__REGR_SXX)
(string("REGR_SXY"), WF__REGR_SXY)
(string("REGR_SYY"), WF__REGR_SYY)
(string("UDAF_FUNC"), WF__UDAF)
;
(string("COUNT(*)"), WF__COUNT_ASTERISK)
(string("COUNT"), WF__COUNT)
(string("SUM"), WF__SUM)
(string("AVG"), WF__AVG)
(string("MIN"), WF__MIN)
(string("MAX"), WF__MAX)
(string("COUNT_DISTINCT"), WF__COUNT_DISTINCT)
(string("SUM_DISTINCT"), WF__SUM_DISTINCT)
(string("AVG_DISTINCT"), WF__AVG_DISTINCT)
(string("MIN_DISTINCT"), WF__MIN)
(string("MAX_DISTINCT"), WF__MAX)
(string("STD"), WF__STDDEV_POP)
(string("STDDEV"), WF__STDDEV_POP)
(string("STDDEV_POP"), WF__STDDEV_POP)
(string("STDDEV_SAMP"), WF__STDDEV_SAMP)
(string("VARIANCE"), WF__VAR_POP)
(string("VAR_POP"), WF__VAR_POP)
(string("VAR_SAMP"), WF__VAR_SAMP)
(string("ROW_NUMBER"), WF__ROW_NUMBER)
(string("RANK"), WF__RANK)
(string("PERCENT_RANK"), WF__PERCENT_RANK)
(string("DENSE_RANK"), WF__DENSE_RANK)
(string("CUME_DIST"), WF__CUME_DIST)
(string("FIRST_VALUE"), WF__FIRST_VALUE)
(string("LAST_VALUE"), WF__LAST_VALUE)
(string("NTH_VALUE"), WF__NTH_VALUE)
(string("LAG"), WF__LAG)
(string("LEAD"), WF__LEAD)
(string("NTILE"), WF__NTILE)
(string("MEDIAN"), WF__PERCENTILE_CONT)
(string("PERCENTILE"), WF__PERCENTILE_CONT)
(string("PERCENTILE_CONT"), WF__PERCENTILE_CONT)
(string("PERCENTILE_DISC"), WF__PERCENTILE_DISC)
(string("REGR_SLOPE"), WF__REGR_SLOPE)
(string("REGR_INTERCEPT"), WF__REGR_INTERCEPT)
(string("REGR_COUNT"), WF__REGR_COUNT)
(string("REGR_R2"), WF__REGR_R2)
(string("REGR_AVGX"), WF__REGR_AVGX)
(string("REGR_AVGY"), WF__REGR_AVGY)
(string("REGR_SXX"), WF__REGR_SXX)
(string("REGR_SXY"), WF__REGR_SXY)
(string("REGR_SYY"), WF__REGR_SYY)
(string("UDAF_FUNC"), WF__UDAF)
;
boost::shared_ptr<WindowFunctionType>
WindowFunctionType::makeWindowFunction(const string& name, int ct, WindowFunctionColumn* wc)
WindowFunctionType::makeWindowFunction(const string& name, int ct, WindowFunctionColumn* wc)
{
boost::shared_ptr<WindowFunctionType> af;
int functionId = windowFunctionId[algorithm::to_upper_copy(name)];
// The template parameters here are dummies to execute the static makeFunction
// which sets the real type based on ct.
switch (functionId)
{
case WF__COUNT_ASTERISK:
case WF__COUNT:
case WF__COUNT_DISTINCT:
af = WF_count<int64_t>::makeFunction(functionId, name, ct);
break;
case WF__MIN:
case WF__MAX:
af = WF_min_max<int64_t>::makeFunction(functionId, name, ct);
break;
case WF__SUM:
case WF__AVG:
case WF__SUM_DISTINCT:
case WF__AVG_DISTINCT:
af = WF_sum_avg<int64_t>::makeFunction(functionId, name, ct);
break;
case WF__STDDEV_POP:
case WF__STDDEV_SAMP:
case WF__VAR_POP:
case WF__VAR_SAMP:
af = WF_stats<int64_t>::makeFunction(functionId, name, ct);
break;
case WF__ROW_NUMBER:
af = WF_row_number::makeFunction(functionId, name, ct);
break;
case WF__RANK:
case WF__DENSE_RANK:
case WF__PERCENT_RANK:
case WF__CUME_DIST:
af = WF_ranking::makeFunction(functionId, name, ct);
break;
case WF__FIRST_VALUE:
case WF__LAST_VALUE:
case WF__NTH_VALUE:
af = WF_nth_value<int64_t>::makeFunction(functionId, name, ct);
break;
case WF__LEAD:
case WF__LAG:
af = WF_lead_lag<int64_t>::makeFunction(functionId, name, ct);
break;
case WF__NTILE:
af = WF_ntile::makeFunction(functionId, name, ct);
break;
case WF__PERCENTILE_CONT:
case WF__PERCENTILE_DISC:
af = WF_percentile<int64_t>::makeFunction(functionId, name, ct);
break;
case WF__UDAF:
af = WF_udaf<int64_t>::makeFunction(functionId, name, ct, wc->getUDAFContext());
break;
case WF__REGR_SLOPE:
case WF__REGR_INTERCEPT:
case WF__REGR_COUNT:
case WF__REGR_R2:
case WF__REGR_AVGX:
case WF__REGR_AVGY:
case WF__REGR_SXX:
case WF__REGR_SXY:
case WF__REGR_SYY:
case WF__UNDEFINED:
default:
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ERR_WF_NOT_SUPPORT, name),
ERR_WF_NOT_SUPPORT);
break;
}
boost::shared_ptr<WindowFunctionType> af;
int functionId = windowFunctionId[algorithm::to_upper_copy(name)];
return af;
// The template parameters here are dummies to execute the static makeFunction
// which sets the real type based on ct.
switch (functionId)
{
case WF__COUNT_ASTERISK:
case WF__COUNT:
case WF__COUNT_DISTINCT:
af = WF_count<int64_t>::makeFunction(functionId, name, ct);
break;
case WF__MIN:
case WF__MAX:
af = WF_min_max<int64_t>::makeFunction(functionId, name, ct);
break;
case WF__SUM:
case WF__AVG:
case WF__SUM_DISTINCT:
case WF__AVG_DISTINCT:
af = WF_sum_avg<int64_t>::makeFunction(functionId, name, ct);
break;
case WF__STDDEV_POP:
case WF__STDDEV_SAMP:
case WF__VAR_POP:
case WF__VAR_SAMP:
af = WF_stats<int64_t>::makeFunction(functionId, name, ct);
break;
case WF__ROW_NUMBER:
af = WF_row_number::makeFunction(functionId, name, ct);
break;
case WF__RANK:
case WF__DENSE_RANK:
case WF__PERCENT_RANK:
case WF__CUME_DIST:
af = WF_ranking::makeFunction(functionId, name, ct);
break;
case WF__FIRST_VALUE:
case WF__LAST_VALUE:
case WF__NTH_VALUE:
af = WF_nth_value<int64_t>::makeFunction(functionId, name, ct);
break;
case WF__LEAD:
case WF__LAG:
af = WF_lead_lag<int64_t>::makeFunction(functionId, name, ct);
break;
case WF__NTILE:
af = WF_ntile::makeFunction(functionId, name, ct);
break;
case WF__PERCENTILE_CONT:
case WF__PERCENTILE_DISC:
af = WF_percentile<int64_t>::makeFunction(functionId, name, ct);
break;
case WF__UDAF:
af = WF_udaf<int64_t>::makeFunction(functionId, name, ct, wc->getUDAFContext());
break;
case WF__REGR_SLOPE:
case WF__REGR_INTERCEPT:
case WF__REGR_COUNT:
case WF__REGR_R2:
case WF__REGR_AVGX:
case WF__REGR_AVGY:
case WF__REGR_SXX:
case WF__REGR_SXY:
case WF__REGR_SYY:
case WF__UNDEFINED:
default:
throw IDBExcept(IDBErrorInfo::instance()->errorMsg(ERR_WF_NOT_SUPPORT, name),
ERR_WF_NOT_SUPPORT);
break;
}
return af;
}
const string WindowFunctionType::toString() const
{
ostringstream oss;
oss << "Window Function Id: " << fFunctionId << ", field indices: ";
for (uint64_t i = 0; i < fFieldIndex.size(); i++)
oss << fFieldIndex[i] << " ";
oss << endl;
ostringstream oss;
oss << "Window Function Id: " << fFunctionId << ", field indices: ";
return oss.str();
for (uint64_t i = 0; i < fFieldIndex.size(); i++)
oss << fFieldIndex[i] << " ";
oss << endl;
return oss.str();
}
template<typename T> void WindowFunctionType::getValue(uint64_t i, T& t, CDT* cdt)
@ -235,44 +249,48 @@ template<typename T> void WindowFunctionType::getValue(uint64_t i, T& t, CDT* cd
template<> void WindowFunctionType::getValue<int64_t>(uint64_t i, int64_t& t, CDT* cdt)
{
t = fRow.getIntField(i);
if (cdt)
{
*cdt = execplan::CalpontSystemCatalog::BIGINT;
}
t = fRow.getIntField(i);
if (cdt)
{
*cdt = execplan::CalpontSystemCatalog::BIGINT;
}
}
template<> void WindowFunctionType::getValue<uint64_t>(uint64_t i, uint64_t& t, CDT* cdt)
{
t = fRow.getUintField(i);
if (cdt)
{
*cdt = execplan::CalpontSystemCatalog::UBIGINT;
}
t = fRow.getUintField(i);
if (cdt)
{
*cdt = execplan::CalpontSystemCatalog::UBIGINT;
}
}
template<> void WindowFunctionType::getValue<double>(uint64_t i, double& t, CDT* cdt)
{
t = fRow.getDoubleField(i);
if (cdt)
{
*cdt = execplan::CalpontSystemCatalog::DOUBLE;
}
t = fRow.getDoubleField(i);
if (cdt)
{
*cdt = execplan::CalpontSystemCatalog::DOUBLE;
}
}
template<> void WindowFunctionType::getValue<float>(uint64_t i, float& t, CDT* cdt)
{
t = fRow.getFloatField(i);
if (cdt)
{
*cdt = execplan::CalpontSystemCatalog::FLOAT;
}
t = fRow.getFloatField(i);
if (cdt)
{
*cdt = execplan::CalpontSystemCatalog::FLOAT;
}
}
template<> void WindowFunctionType::getValue<string>(uint64_t i, string& t, CDT* cdt)
{
t = fRow.getStringField(i);
// By not setting cdt, we let it default to the column's type
t = fRow.getStringField(i);
// By not setting cdt, we let it default to the column's type
}
template<typename T> void WindowFunctionType::setValue(uint64_t i, T& t)
@ -281,122 +299,134 @@ template<typename T> void WindowFunctionType::setValue(uint64_t i, T& t)
template<> void WindowFunctionType::setValue<int64_t>(uint64_t i, int64_t& t)
{
fRow.setIntField(t, i);
fRow.setIntField(t, i);
}
template<> void WindowFunctionType::setValue<uint64_t>(uint64_t i, uint64_t& t)
{
fRow.setUintField(t, i);
fRow.setUintField(t, i);
}
template<> void WindowFunctionType::setValue<double>(uint64_t i, double& t)
{
fRow.setDoubleField(t, i);
fRow.setDoubleField(t, i);
}
template<> void WindowFunctionType::setValue<float>(uint64_t i, float& t)
{
fRow.setFloatField(t, i);
fRow.setFloatField(t, i);
}
template<> void WindowFunctionType::setValue<string>(uint64_t i, string& t)
{
fRow.setStringField(t, i);
fRow.setStringField(t, i);
}
template<typename T>
void WindowFunctionType::setValue(int ct, int64_t b, int64_t e, int64_t c, T* v)
{
if (c != WF__BOUND_ALL)
b = e = c;
if (c != WF__BOUND_ALL)
b = e = c;
uint64_t i = fFieldIndex[0];
if (v == NULL)
v = (T*) getNullValueByType(ct, i);
uint64_t i = fFieldIndex[0];
for (int64_t j = b; j <= e; j++)
{
if (j % 1000 == 0 && fStep->cancelled())
break;
if (v == NULL)
v = (T*) getNullValueByType(ct, i);
fRow.setData(getPointer((*fRowData)[j]));
setValue(i, *v);
}
for (int64_t j = b; j <= e; j++)
{
if (j % 1000 == 0 && fStep->cancelled())
break;
fRow.setData(getPointer((*fRowData)[j]));
setValue(i, *v);
}
}
template<typename T>
void WindowFunctionType::implicit2T(uint64_t i, T& t, int s)
{
int ct = fRow.getColType(i);
int pw = 0;
switch (ct)
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
{
t = (T) fRow.getIntField(i);
pw = s - fRow.getScale(i); // pw is difference of scales, will be in [-18, 18]
if (pw > 0)
t *= IDB_pow[pw];
else if (pw < 0)
t /= IDB_pow[-pw];
break;
}
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UDECIMAL:
{
t = (T) fRow.getUintField(i);
pw = s - fRow.getScale(i); // pw is difference of scales, will be in [-18, 18]
if (pw > 0)
t *= IDB_pow[pw];
else if (pw < 0)
t /= IDB_pow[-pw];
break;
}
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
{
if (s == 0)
t = (T) fRow.getDoubleField(i);
else
t = (T) (fRow.getDoubleField(i) * IDB_pow[s]); // s is scale, [0, 18]
break;
}
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
{
if (s == 0)
t = (T) fRow.getFloatField(i);
else
t = (T) (fRow.getFloatField(i) * IDB_pow[s]); // s is scale, [0, 18]
break;
}
case CalpontSystemCatalog::CHAR:
case CalpontSystemCatalog::VARCHAR:
default:
{
string errStr = fFunctionName + "(" + colType2String[ct] + ")";
errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_INVALID_PARM_TYPE, errStr);
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_INVALID_PARM_TYPE);
int ct = fRow.getColType(i);
int pw = 0;
break;
}
}
switch (ct)
{
case CalpontSystemCatalog::TINYINT:
case CalpontSystemCatalog::SMALLINT:
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
case CalpontSystemCatalog::BIGINT:
case CalpontSystemCatalog::DECIMAL:
{
t = (T) fRow.getIntField(i);
pw = s - fRow.getScale(i); // pw is difference of scales, will be in [-18, 18]
if (pw > 0)
t *= IDB_pow[pw];
else if (pw < 0)
t /= IDB_pow[-pw];
break;
}
case CalpontSystemCatalog::UTINYINT:
case CalpontSystemCatalog::USMALLINT:
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
case CalpontSystemCatalog::UBIGINT:
case CalpontSystemCatalog::UDECIMAL:
{
t = (T) fRow.getUintField(i);
pw = s - fRow.getScale(i); // pw is difference of scales, will be in [-18, 18]
if (pw > 0)
t *= IDB_pow[pw];
else if (pw < 0)
t /= IDB_pow[-pw];
break;
}
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
{
if (s == 0)
t = (T) fRow.getDoubleField(i);
else
t = (T) (fRow.getDoubleField(i) * IDB_pow[s]); // s is scale, [0, 18]
break;
}
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
{
if (s == 0)
t = (T) fRow.getFloatField(i);
else
t = (T) (fRow.getFloatField(i) * IDB_pow[s]); // s is scale, [0, 18]
break;
}
case CalpontSystemCatalog::CHAR:
case CalpontSystemCatalog::VARCHAR:
default:
{
string errStr = fFunctionName + "(" + colType2String[ct] + ")";
errStr = IDBErrorInfo::instance()->errorMsg(ERR_WF_INVALID_PARM_TYPE, errStr);
cerr << errStr << endl;
throw IDBExcept(errStr, ERR_WF_INVALID_PARM_TYPE);
break;
}
}
}
template<>
void WindowFunctionType::implicit2T<string>(uint64_t i, string& t, int)
{
t = fRow.getStringField(i);
t = fRow.getStringField(i);
}
template<typename T>
@ -407,31 +437,31 @@ void WindowFunctionType::getConstValue(ConstantColumn* cc, T& t, bool& b)
template<>
void WindowFunctionType::getConstValue<int64_t>(ConstantColumn* cc, int64_t& t, bool& b)
{
t = cc->getIntVal(fRow, b);
t = cc->getIntVal(fRow, b);
}
template<>
void WindowFunctionType::getConstValue<uint64_t>(ConstantColumn* cc, uint64_t& t, bool& b)
{
t = cc->getUintVal(fRow, b);
t = cc->getUintVal(fRow, b);
}
template<>
void WindowFunctionType::getConstValue<double>(ConstantColumn* cc, double& t, bool& b)
{
t = cc->getDoubleVal(fRow, b);
t = cc->getDoubleVal(fRow, b);
}
template<>
void WindowFunctionType::getConstValue<float>(ConstantColumn* cc, float& t, bool& b)
{
t = cc->getFloatVal(fRow, b);
t = cc->getFloatVal(fRow, b);
}
template<>
void WindowFunctionType::getConstValue<string>(ConstantColumn* cc, string& t, bool& b)
{
t = cc->getStrVal(fRow, b);
t = cc->getStrVal(fRow, b);
}
template void WindowFunctionType::implicit2T<int64_t>(uint64_t, int64_t&, int);
@ -448,122 +478,152 @@ template void WindowFunctionType::setValue<string>(int, int64_t, int64_t, int64_
void* WindowFunctionType::getNullValueByType(int ct, int pos)
{
static uint64_t bigIntNull = joblist::BIGINTNULL;
static uint64_t intNull = joblist::INTNULL;
static uint64_t smallIntNull = joblist::SMALLINTNULL;
static uint64_t tinyIntNull = joblist::TINYINTNULL;
static uint64_t ubigIntNull = joblist::UBIGINTNULL;
static uint64_t uintNull = joblist::UINTNULL;
static uint64_t usmallIntNull = joblist::USMALLINTNULL;
static uint64_t utinyIntNull = joblist::UTINYINTNULL;
static uint64_t floatNull = joblist::FLOATNULL;
static uint64_t doubleNull = joblist::DOUBLENULL;
static uint64_t dateNull = joblist::DATENULL;
static uint64_t datetimeNull = joblist::DATETIMENULL;
static uint64_t char1Null = joblist::CHAR1NULL;
static uint64_t char2Null = joblist::CHAR2NULL;
static uint64_t char4Null = joblist::CHAR4NULL;
static uint64_t char8Null = joblist::CHAR8NULL;
static string stringNull("");
static uint64_t bigIntNull = joblist::BIGINTNULL;
static uint64_t intNull = joblist::INTNULL;
static uint64_t smallIntNull = joblist::SMALLINTNULL;
static uint64_t tinyIntNull = joblist::TINYINTNULL;
static uint64_t ubigIntNull = joblist::UBIGINTNULL;
static uint64_t uintNull = joblist::UINTNULL;
static uint64_t usmallIntNull = joblist::USMALLINTNULL;
static uint64_t utinyIntNull = joblist::UTINYINTNULL;
static uint64_t floatNull = joblist::FLOATNULL;
static uint64_t doubleNull = joblist::DOUBLENULL;
static uint64_t dateNull = joblist::DATENULL;
static uint64_t datetimeNull = joblist::DATETIMENULL;
static uint64_t char1Null = joblist::CHAR1NULL;
static uint64_t char2Null = joblist::CHAR2NULL;
static uint64_t char4Null = joblist::CHAR4NULL;
static uint64_t char8Null = joblist::CHAR8NULL;
static string stringNull("");
void* v = NULL;
switch (ct) {
case CalpontSystemCatalog::TINYINT:
v = &tinyIntNull;
break;
case CalpontSystemCatalog::SMALLINT:
v = &smallIntNull;
break;
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
v = &intNull;
break;
case CalpontSystemCatalog::BIGINT:
v = &bigIntNull;
break;
case CalpontSystemCatalog::DATE:
v = &dateNull;
break;
case CalpontSystemCatalog::DATETIME:
v = &datetimeNull;
break;
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
v = &floatNull;
break;
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
v = &doubleNull;
break;
case CalpontSystemCatalog::CHAR:
case CalpontSystemCatalog::VARCHAR: {
uint64_t len = fRow.getColumnWidth(pos);
switch (len) {
case 1:
v = &char1Null;
break;
case 2:
v = &char2Null;
break;
case 3:
case 4:
v = &char4Null;
break;
case 5:
case 6:
case 7:
case 8:
v = &char8Null;
break;
default:
v = &stringNull;
break;
}
break;
}
case CalpontSystemCatalog::DECIMAL:
case CalpontSystemCatalog::UDECIMAL:
{
uint64_t len = fRow.getColumnWidth(pos);
switch (len) {
case 1:
v = &tinyIntNull;
break;
case 2:
v = &smallIntNull;
break;
case 4:
v = &intNull;
break;
default:
v = &bigIntNull;
break;
}
break;
}
case CalpontSystemCatalog::UTINYINT:
v = &utinyIntNull;
break;
case CalpontSystemCatalog::USMALLINT:
v = &usmallIntNull;
break;
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
v = &uintNull;
break;
case CalpontSystemCatalog::UBIGINT:
v = &ubigIntNull;
break;
case CalpontSystemCatalog::LONGDOUBLE:
case CalpontSystemCatalog::VARBINARY:
default:
std::ostringstream oss;
oss << "not supported data type: " << colType2String[ct];
throw logic_error(oss.str());
break;
}
void* v = NULL;
return v;
switch (ct)
{
case CalpontSystemCatalog::TINYINT:
v = &tinyIntNull;
break;
case CalpontSystemCatalog::SMALLINT:
v = &smallIntNull;
break;
case CalpontSystemCatalog::MEDINT:
case CalpontSystemCatalog::INT:
v = &intNull;
break;
case CalpontSystemCatalog::BIGINT:
v = &bigIntNull;
break;
case CalpontSystemCatalog::DATE:
v = &dateNull;
break;
case CalpontSystemCatalog::DATETIME:
v = &datetimeNull;
break;
case CalpontSystemCatalog::FLOAT:
case CalpontSystemCatalog::UFLOAT:
v = &floatNull;
break;
case CalpontSystemCatalog::DOUBLE:
case CalpontSystemCatalog::UDOUBLE:
v = &doubleNull;
break;
case CalpontSystemCatalog::CHAR:
case CalpontSystemCatalog::VARCHAR:
{
uint64_t len = fRow.getColumnWidth(pos);
switch (len)
{
case 1:
v = &char1Null;
break;
case 2:
v = &char2Null;
break;
case 3:
case 4:
v = &char4Null;
break;
case 5:
case 6:
case 7:
case 8:
v = &char8Null;
break;
default:
v = &stringNull;
break;
}
break;
}
case CalpontSystemCatalog::DECIMAL:
case CalpontSystemCatalog::UDECIMAL:
{
uint64_t len = fRow.getColumnWidth(pos);
switch (len)
{
case 1:
v = &tinyIntNull;
break;
case 2:
v = &smallIntNull;
break;
case 4:
v = &intNull;
break;
default:
v = &bigIntNull;
break;
}
break;
}
case CalpontSystemCatalog::UTINYINT:
v = &utinyIntNull;
break;
case CalpontSystemCatalog::USMALLINT:
v = &usmallIntNull;
break;
case CalpontSystemCatalog::UMEDINT:
case CalpontSystemCatalog::UINT:
v = &uintNull;
break;
case CalpontSystemCatalog::UBIGINT:
v = &ubigIntNull;
break;
case CalpontSystemCatalog::LONGDOUBLE:
case CalpontSystemCatalog::VARBINARY:
default:
std::ostringstream oss;
oss << "not supported data type: " << colType2String[ct];
throw logic_error(oss.str());
break;
}
return v;
}
} //namespace

199
utils/windowfunction/windowfunctiontype.h Executable file → Normal file
View File

@ -108,102 +108,161 @@ typedef execplan::CalpontSystemCatalog::ColDataType CDT;
class WindowFunctionType
{
public:
// @brief WindowFunctionType constructor
WindowFunctionType(int id = 0, const std::string& name = "") :
fFunctionId(id), fFunctionName(name), fFrameUnit(0) {};
// @brief WindowFunctionType constructor
WindowFunctionType(int id = 0, const std::string& name = "") :
fFunctionId(id), fFunctionName(name), fFrameUnit(0) {};
// use default copy construct
//WindowFunctionType(const WindowFunctionType&);
// use default copy construct
//WindowFunctionType(const WindowFunctionType&);
// @brief WindowFunctionType destructor
virtual ~WindowFunctionType() {};
// @brief WindowFunctionType destructor
virtual ~WindowFunctionType() {};
// @brief virtual operator(begin, end, current, data, row)
virtual void operator()(int64_t, int64_t, int64_t) = 0;
// @brief virtual operator(begin, end, current, data, row)
virtual void operator()(int64_t, int64_t, int64_t) = 0;
// @brief virtual clone()
virtual WindowFunctionType* clone() const = 0;
// @brief virtual clone()
virtual WindowFunctionType* clone() const = 0;
// @brief virtual resetData()
virtual void resetData() { fPrev = -1; }
// @brief virtual resetData()
virtual void resetData()
{
fPrev = -1;
}
// @brief virtual parseParms()
virtual void parseParms(const std::vector<execplan::SRCP>&) {}
// @brief virtual parseParms()
virtual void parseParms(const std::vector<execplan::SRCP>&) {}
// @brief virtual dropValues() For UDAnF functions
// return false if there's no dropValue() implemented in the function.
virtual bool dropValues(int64_t, int64_t) {return false;}
// @brief virtual dropValues() For UDAnF functions
// return false if there's no dropValue() implemented in the function.
virtual bool dropValues(int64_t, int64_t)
{
return false;
}
// @brief virtual display method
virtual const std::string toString() const;
// @brief virtual display method
virtual const std::string toString() const;
// @brief access methods
int64_t functionId() const { return fFunctionId; }
void functionId(int id) { fFunctionId = id; }
const std::vector<int64_t>& fieldIndex() const { return fFieldIndex; }
void fieldIndex(const std::vector<int64_t>& v) { fFieldIndex = v; }
void setRowMetaData(const rowgroup::RowGroup& g, const rowgroup::Row& r)
{ fRowGroup = g; fRow = r; }
void setRowData(const boost::shared_ptr<std::vector<joblist::RowPosition> >& d) {fRowData = d;}
int64_t frameUnit() const { return fFrameUnit; }
void frameUnit(int u) { fFrameUnit = u; }
std::pair<int64_t, int64_t> partition() const { return fPartition; }
void partition(std::pair<int64_t, int64_t>& p) { fPartition = p; }
const boost::shared_ptr<ordering::EqualCompData>& peer() const { return fPeer; }
void peer(const boost::shared_ptr<ordering::EqualCompData>& p) { fPeer = p; }
void setCallback(joblist::WindowFunctionStep* step) { fStep = step; }
// @brief access methods
int64_t functionId() const
{
return fFunctionId;
}
void functionId(int id)
{
fFunctionId = id;
}
const std::vector<int64_t>& fieldIndex() const
{
return fFieldIndex;
}
void fieldIndex(const std::vector<int64_t>& v)
{
fFieldIndex = v;
}
void setRowMetaData(const rowgroup::RowGroup& g, const rowgroup::Row& r)
{
fRowGroup = g;
fRow = r;
}
void setRowData(const boost::shared_ptr<std::vector<joblist::RowPosition> >& d)
{
fRowData = d;
}
int64_t frameUnit() const
{
return fFrameUnit;
}
void frameUnit(int u)
{
fFrameUnit = u;
}
std::pair<int64_t, int64_t> partition() const
{
return fPartition;
}
void partition(std::pair<int64_t, int64_t>& p)
{
fPartition = p;
}
const boost::shared_ptr<ordering::EqualCompData>& peer() const
{
return fPeer;
}
void peer(const boost::shared_ptr<ordering::EqualCompData>& p)
{
fPeer = p;
}
void setCallback(joblist::WindowFunctionStep* step)
{
fStep = step;
}
static boost::shared_ptr<WindowFunctionType> makeWindowFunction(const std::string&, int ct, WindowFunctionColumn* wc);
static boost::shared_ptr<WindowFunctionType> makeWindowFunction(const std::string&, int ct, WindowFunctionColumn* wc);
protected:
static std::map<std::string, int> windowFunctionId;
static std::map<std::string, int> windowFunctionId;
// utility methods
template<typename T> void getValue(uint64_t, T&, CDT* cdt = NULL);
template<typename T> void setValue(int, int64_t, int64_t, int64_t, T* = NULL);
template<typename T> void setValue(uint64_t, T&);
template<typename T> void implicit2T(uint64_t, T&, int);
template<typename T> void getConstValue(execplan::ConstantColumn*, T&, bool&);
// utility methods
template<typename T> void getValue(uint64_t, T&, CDT* cdt = NULL);
template<typename T> void setValue(int, int64_t, int64_t, int64_t, T* = NULL);
template<typename T> void setValue(uint64_t, T&);
template<typename T> void implicit2T(uint64_t, T&, int);
template<typename T> void getConstValue(execplan::ConstantColumn*, T&, bool&);
virtual void* getNullValueByType(int, int);
virtual void* getNullValueByType(int, int);
int64_t getIntValue(uint64_t i) { return fRow.getIntField(i); }
double getDoubleValue(uint64_t i) { return fRow.getDoubleField(i); }
void setIntValue(int64_t i, int64_t v) { fRow.setIntField(v, i); }
void setDoubleValue(int64_t i, double v) { fRow.setDoubleField(v, i); }
int64_t getIntValue(uint64_t i)
{
return fRow.getIntField(i);
}
double getDoubleValue(uint64_t i)
{
return fRow.getDoubleField(i);
}
void setIntValue(int64_t i, int64_t v)
{
fRow.setIntField(v, i);
}
void setDoubleValue(int64_t i, double v)
{
fRow.setDoubleField(v, i);
}
// for string table
rowgroup::Row::Pointer getPointer(joblist::RowPosition& r)
{ return fStep->getPointer(r, fRowGroup, fRow); }
// for string table
rowgroup::Row::Pointer getPointer(joblist::RowPosition& r)
{
return fStep->getPointer(r, fRowGroup, fRow);
}
// function type
int64_t fFunctionId;
std::string fFunctionName;
// function type
int64_t fFunctionId;
std::string fFunctionName;
// output and input field indices: [0] - output
std::vector<int64_t> fFieldIndex;
// output and input field indices: [0] - output
std::vector<int64_t> fFieldIndex;
// row meta data
rowgroup::RowGroup fRowGroup;
rowgroup::Row fRow;
// row meta data
rowgroup::RowGroup fRowGroup;
rowgroup::Row fRow;
// data set
boost::shared_ptr<std::vector<joblist::RowPosition> > fRowData;
// data set
boost::shared_ptr<std::vector<joblist::RowPosition> > fRowData;
// frame unit ( ROWS | RANGE )
int64_t fFrameUnit;
// frame unit ( ROWS | RANGE )
int64_t fFrameUnit;
// partition
std::pair<int64_t, int64_t> fPartition;
// partition
std::pair<int64_t, int64_t> fPartition;
// functor for peer checking
boost::shared_ptr<ordering::EqualCompData> fPeer;
int64_t fPrev;
// functor for peer checking
boost::shared_ptr<ordering::EqualCompData> fPeer;
int64_t fPrev;
// for checking if query is cancelled
joblist::WindowFunctionStep* fStep;
// for checking if query is cancelled
joblist::WindowFunctionStep* fStep;
};