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);
    }
}
Example #2
0
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);
	}
}