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; for (int64_t c = s; c <= t; c++) { if (c % 1000 == 0 && fStep->cancelled()) break; 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); } 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; } } 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); } }
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); } } } if (fNveNull) { 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); } return; } 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))); if (fRow.isNullValue(idx)) continue; // ignore nulls if (b1 == -1) b1 = c; e1 = 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; } rk[c-b] = rank; } } 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; } 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); } }