mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-02-02 08:00:39 +01:00
Add window functions, PERCENT_RANK(), CUME_DIST() and NTILE().
This commit is contained in:
parent
783806a4ed
commit
8745489bb0
@ -144,6 +144,9 @@ Syntax:
|
||||
<ranking window function> ::=
|
||||
DENSE_RANK() |
|
||||
RANK() |
|
||||
PERCENT_RANK() |
|
||||
CUME_DIST() |
|
||||
NTILE(<expr>) |
|
||||
ROW_NUMBER()
|
||||
|
||||
The rank functions compute the ordinal rank of a row within the window partition. In this category
|
||||
@ -158,6 +161,9 @@ select
|
||||
salary,
|
||||
dense_rank() over (order by salary),
|
||||
rank() over (order by salary),
|
||||
percent_rank() over (order by salary),
|
||||
cume_dist() over (order by salary),
|
||||
ntile(3) over (order by salary),
|
||||
row_number() over (order by salary),
|
||||
sum(1) over (order by salary)
|
||||
from employee
|
||||
@ -165,18 +171,21 @@ select
|
||||
|
||||
And the result set:
|
||||
|
||||
id salary dense_rank rank row_number sum
|
||||
-- ------ ---------- ---- ---------- ---
|
||||
3 8.00 1 1 1 1
|
||||
4 9.00 2 2 2 2
|
||||
1 10.00 3 3 3 4
|
||||
5 10.00 3 3 4 4
|
||||
2 12.00 4 5 5 5
|
||||
id salary dense_rank rank percent_rank cume_dist ntile row_number sum
|
||||
-- ------ ---------- ---- ------------------ -------------------- ------ ---------- ---
|
||||
3 8.00 1 1 0.000000000000000 0.2000000000000000 1 1 1
|
||||
4 9.00 2 2 0.2500000000000000 0.4000000000000000 1 2 2
|
||||
1 10.00 3 3 0.5000000000000000 0.8000000000000000 2 3 4
|
||||
5 10.00 3 3 0.5000000000000000 0.8000000000000000 2 4 4
|
||||
2 12.00 4 5 1.000000000000000 1.000000000000000 3 5 5
|
||||
|
||||
The difference between DENSE_RANK and RANK is that there is a gap related to duplicate rows (in
|
||||
relation to the window ordering) only in RANK. DENSE_RANK continues assigning sequential numbers
|
||||
after the duplicate salary. On the other hand, ROW_NUMBER always assigns sequential numbers, even
|
||||
when there is duplicate values.
|
||||
PERCENT_RANK is a ratio of RANK to group count.
|
||||
CUME_DIST is cumulative distribution of a value in a group.
|
||||
NTILE distributes the rows into a specified number of groups.
|
||||
|
||||
4.2 Navigational functions
|
||||
--------------------------
|
||||
|
@ -425,7 +425,7 @@ void AggNode::aggFinish(thread_db* /*tdbb*/, jrd_req* request) const
|
||||
}
|
||||
}
|
||||
|
||||
dsc* AggNode::execute(thread_db* tdbb, jrd_req* request) const
|
||||
dsc* AggNode::execute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
|
||||
@ -464,7 +464,14 @@ dsc* AggNode::execute(thread_db* tdbb, jrd_req* request) const
|
||||
}
|
||||
}
|
||||
|
||||
return aggExecute(tdbb, request);
|
||||
return aggExecute(tdbb, request, win_row_count);
|
||||
}
|
||||
|
||||
|
||||
dsc* AggNode::execute(thread_db* tdbb, jrd_req* request) const
|
||||
{
|
||||
fb_assert(false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -652,7 +659,7 @@ void AvgAggNode::aggPass(thread_db* /*tdbb*/, jrd_req* request, dsc* desc) const
|
||||
ArithmeticNode::add2(desc, impure, this, blr_add);
|
||||
}
|
||||
|
||||
dsc* AvgAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
|
||||
dsc* AvgAggNode::aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
|
||||
@ -797,7 +804,7 @@ void ListAggNode::aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const
|
||||
impure->vlu_blob->BLB_put_data(tdbb, temp, len);
|
||||
}
|
||||
|
||||
dsc* ListAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
|
||||
dsc* ListAggNode::aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
|
||||
@ -904,7 +911,7 @@ void CountAggNode::aggPass(thread_db* /*tdbb*/, jrd_req* request, dsc* /*desc*/)
|
||||
++impure->vlu_misc.vlu_int64;
|
||||
}
|
||||
|
||||
dsc* CountAggNode::aggExecute(thread_db* /*tdbb*/, jrd_req* request) const
|
||||
dsc* CountAggNode::aggExecute(thread_db* /*tdbb*/, jrd_req* request, FB_UINT64 win_row_count) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
|
||||
@ -1141,7 +1148,7 @@ void SumAggNode::aggPass(thread_db* /*tdbb*/, jrd_req* request, dsc* desc) const
|
||||
ArithmeticNode::add2(desc, impure, this, blr_add);
|
||||
}
|
||||
|
||||
dsc* SumAggNode::aggExecute(thread_db* /*tdbb*/, jrd_req* request) const
|
||||
dsc* SumAggNode::aggExecute(thread_db* /*tdbb*/, jrd_req* request, FB_UINT64 win_row_count) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
|
||||
@ -1232,7 +1239,7 @@ void MaxMinAggNode::aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const
|
||||
EVL_make_value(tdbb, desc, impure);
|
||||
}
|
||||
|
||||
dsc* MaxMinAggNode::aggExecute(thread_db* /*tdbb*/, jrd_req* request) const
|
||||
dsc* MaxMinAggNode::aggExecute(thread_db* /*tdbb*/, jrd_req* request, FB_UINT64 win_row_count) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
|
||||
@ -1338,7 +1345,7 @@ void StdDevAggNode::aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const
|
||||
impure2->x2 += d * d;
|
||||
}
|
||||
|
||||
dsc* StdDevAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
|
||||
dsc* StdDevAggNode::aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
StdDevImpure* impure2 = request->getImpure<StdDevImpure>(impure2Offset);
|
||||
@ -1497,7 +1504,7 @@ void CorrAggNode::aggPass(thread_db* /*tdbb*/, jrd_req* /*request*/, dsc* /*desc
|
||||
fb_assert(false);
|
||||
}
|
||||
|
||||
dsc* CorrAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
|
||||
dsc* CorrAggNode::aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
CorrImpure* impure2 = request->getImpure<CorrImpure>(impure2Offset);
|
||||
@ -1682,7 +1689,7 @@ void RegrAggNode::aggPass(thread_db* /*tdbb*/, jrd_req* /*request*/, dsc* /*desc
|
||||
fb_assert(false);
|
||||
}
|
||||
|
||||
dsc* RegrAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
|
||||
dsc* RegrAggNode::aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
RegrImpure* impure2 = request->getImpure<RegrImpure>(impure2Offset);
|
||||
@ -1839,7 +1846,7 @@ void RegrCountAggNode::aggPass(thread_db* /*tdbb*/, jrd_req* /*request*/, dsc* /
|
||||
fb_assert(false);
|
||||
}
|
||||
|
||||
dsc* RegrCountAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
|
||||
dsc* RegrCountAggNode::aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
|
||||
|
@ -45,7 +45,7 @@ public:
|
||||
|
||||
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const;
|
||||
|
||||
protected:
|
||||
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
|
||||
@ -79,7 +79,7 @@ public:
|
||||
|
||||
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const;
|
||||
|
||||
protected:
|
||||
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
|
||||
@ -103,7 +103,7 @@ public:
|
||||
|
||||
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const;
|
||||
|
||||
protected:
|
||||
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
|
||||
@ -123,7 +123,7 @@ public:
|
||||
|
||||
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const;
|
||||
|
||||
protected:
|
||||
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
|
||||
@ -149,7 +149,7 @@ public:
|
||||
|
||||
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const;
|
||||
|
||||
protected:
|
||||
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
|
||||
@ -186,7 +186,7 @@ public:
|
||||
|
||||
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const;
|
||||
|
||||
protected:
|
||||
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
|
||||
@ -227,7 +227,7 @@ public:
|
||||
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual bool aggPass(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const;
|
||||
|
||||
protected:
|
||||
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
|
||||
@ -274,7 +274,7 @@ public:
|
||||
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual bool aggPass(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const;
|
||||
|
||||
protected:
|
||||
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
|
||||
@ -303,7 +303,7 @@ public:
|
||||
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual bool aggPass(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const;
|
||||
|
||||
protected:
|
||||
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
|
||||
|
@ -974,7 +974,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual dsc* winPass(thread_db* /*tdbb*/, jrd_req* /*request*/, SlidingWindow* /*window*/) const
|
||||
virtual dsc* winPass(thread_db* /*tdbb*/, jrd_req* /*request*/, SlidingWindow* /*window*/, FB_UINT64 /*win_rou_count*/) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@ -983,9 +983,10 @@ public:
|
||||
virtual void aggFinish(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual bool aggPass(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual dsc* execute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual dsc* execute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const;
|
||||
|
||||
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const = 0;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const = 0;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const = 0;
|
||||
|
||||
virtual AggNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
|
||||
|
@ -91,7 +91,7 @@ void DenseRankWinNode::aggPass(thread_db* /*tdbb*/, jrd_req* /*request*/, dsc* /
|
||||
{
|
||||
}
|
||||
|
||||
dsc* DenseRankWinNode::aggExecute(thread_db* /*tdbb*/, jrd_req* request) const
|
||||
dsc* DenseRankWinNode::aggExecute(thread_db* /*tdbb*/, jrd_req* request, FB_UINT64 win_row_count) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
++impure->vlu_misc.vlu_int64;
|
||||
@ -167,7 +167,7 @@ void RankWinNode::aggPass(thread_db* /*tdbb*/, jrd_req* request, dsc* /*desc*/)
|
||||
++impure->vlux_count;
|
||||
}
|
||||
|
||||
dsc* RankWinNode::aggExecute(thread_db* tdbb, jrd_req* request) const
|
||||
dsc* RankWinNode::aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
|
||||
@ -192,6 +192,171 @@ AggNode* RankWinNode::dsqlCopy(DsqlCompilerScratch* /*dsqlScratch*/) /*const*/
|
||||
//--------------------
|
||||
|
||||
|
||||
static WinFuncNode::RegisterFactory0<PercentRankWinNode> percentRankWinInfo("PERCENT_RANK");
|
||||
|
||||
PercentRankWinNode::PercentRankWinNode(MemoryPool& pool)
|
||||
: WinFuncNode(pool, percentRankWinInfo),
|
||||
tempImpure(0)
|
||||
{
|
||||
fb_assert(dsqlChildNodes.getCount() == 1 && jrdChildNodes.getCount() == 1);
|
||||
dsqlChildNodes.clear();
|
||||
jrdChildNodes.clear();
|
||||
}
|
||||
|
||||
string PercentRankWinNode::internalPrint(NodePrinter& printer) const
|
||||
{
|
||||
WinFuncNode::internalPrint(printer);
|
||||
|
||||
NODE_PRINT(printer, tempImpure);
|
||||
|
||||
return "PercentRankWinNode";
|
||||
}
|
||||
|
||||
void PercentRankWinNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc)
|
||||
{
|
||||
desc->makeDouble();
|
||||
}
|
||||
|
||||
void PercentRankWinNode::getDesc(thread_db* /*tdbb*/, CompilerScratch* /*csb*/, dsc* desc)
|
||||
{
|
||||
desc->makeDouble();
|
||||
}
|
||||
|
||||
ValueExprNode* PercentRankWinNode::copy(thread_db* tdbb, NodeCopier& /*copier*/) const
|
||||
{
|
||||
return FB_NEW_POOL(*tdbb->getDefaultPool()) PercentRankWinNode(*tdbb->getDefaultPool());
|
||||
}
|
||||
|
||||
AggNode* PercentRankWinNode::pass2(thread_db* tdbb, CompilerScratch* csb)
|
||||
{
|
||||
AggNode::pass2(tdbb, csb);
|
||||
tempImpure = CMP_impure(csb, sizeof(impure_value_ex));
|
||||
return this;
|
||||
}
|
||||
|
||||
void PercentRankWinNode::aggInit(thread_db* tdbb, jrd_req* request) const
|
||||
{
|
||||
AggNode::aggInit(tdbb, request);
|
||||
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
impure->make_int64(1, 0);
|
||||
impure->vlux_count = 0;
|
||||
}
|
||||
|
||||
void PercentRankWinNode::aggPass(thread_db* /*tdbb*/, jrd_req* request, dsc* /*desc*/) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
++impure->vlux_count;
|
||||
}
|
||||
|
||||
dsc* PercentRankWinNode::aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
|
||||
dsc temp;
|
||||
double d = (double)(impure->vlu_misc.vlu_int64 -1) / (double)(win_row_count -1);
|
||||
temp.makeDouble(&d);
|
||||
|
||||
impure_value_ex* impureTemp = request->getImpure<impure_value_ex>(tempImpure);
|
||||
EVL_make_value(tdbb, &temp, impureTemp);
|
||||
|
||||
impure->vlu_misc.vlu_int64 += impure->vlux_count;
|
||||
impure->vlux_count = 0;
|
||||
|
||||
return &impureTemp->vlu_desc;
|
||||
}
|
||||
|
||||
AggNode* PercentRankWinNode::dsqlCopy(DsqlCompilerScratch* /*dsqlScratch*/) /*const*/
|
||||
{
|
||||
return FB_NEW_POOL(getPool()) PercentRankWinNode(getPool());
|
||||
}
|
||||
|
||||
|
||||
//--------------------
|
||||
|
||||
|
||||
static WinFuncNode::RegisterFactory0<CumeDistWinNode> cumeDistWinInfo("CUME_DIST");
|
||||
|
||||
CumeDistWinNode::CumeDistWinNode(MemoryPool& pool)
|
||||
: WinFuncNode(pool, cumeDistWinInfo),
|
||||
tempImpure(0)
|
||||
{
|
||||
fb_assert(dsqlChildNodes.getCount() == 1 && jrdChildNodes.getCount() == 1);
|
||||
dsqlChildNodes.clear();
|
||||
jrdChildNodes.clear();
|
||||
}
|
||||
|
||||
string CumeDistWinNode::internalPrint(NodePrinter& printer) const
|
||||
{
|
||||
WinFuncNode::internalPrint(printer);
|
||||
|
||||
NODE_PRINT(printer, tempImpure);
|
||||
|
||||
return "CumeDistWinNode";
|
||||
}
|
||||
|
||||
void CumeDistWinNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc)
|
||||
{
|
||||
desc->makeDouble();
|
||||
}
|
||||
|
||||
void CumeDistWinNode::getDesc(thread_db* /*tdbb*/, CompilerScratch* /*csb*/, dsc* desc)
|
||||
{
|
||||
desc->makeDouble();
|
||||
}
|
||||
|
||||
ValueExprNode* CumeDistWinNode::copy(thread_db* tdbb, NodeCopier& /*copier*/) const
|
||||
{
|
||||
return FB_NEW_POOL(*tdbb->getDefaultPool()) CumeDistWinNode(*tdbb->getDefaultPool());
|
||||
}
|
||||
|
||||
AggNode* CumeDistWinNode::pass2(thread_db* tdbb, CompilerScratch* csb)
|
||||
{
|
||||
AggNode::pass2(tdbb, csb);
|
||||
tempImpure = CMP_impure(csb, sizeof(impure_value_ex));
|
||||
return this;
|
||||
}
|
||||
|
||||
void CumeDistWinNode::aggInit(thread_db* tdbb, jrd_req* request) const
|
||||
{
|
||||
AggNode::aggInit(tdbb, request);
|
||||
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
impure->make_int64(1, 0);
|
||||
impure->vlux_count = 0;
|
||||
}
|
||||
|
||||
void CumeDistWinNode::aggPass(thread_db* /*tdbb*/, jrd_req* request, dsc* /*desc*/) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
++impure->vlux_count;
|
||||
}
|
||||
|
||||
dsc* CumeDistWinNode::aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
|
||||
dsc temp;
|
||||
impure->vlu_misc.vlu_int64 += impure->vlux_count;
|
||||
impure->vlux_count = 0;
|
||||
double d = (double)(impure->vlu_misc.vlu_int64 -1) / (double)(win_row_count);
|
||||
temp.makeDouble(&d);
|
||||
|
||||
impure_value_ex* impureTemp = request->getImpure<impure_value_ex>(tempImpure);
|
||||
EVL_make_value(tdbb, &temp, impureTemp);
|
||||
|
||||
return &impureTemp->vlu_desc;
|
||||
}
|
||||
|
||||
AggNode* CumeDistWinNode::dsqlCopy(DsqlCompilerScratch* /*dsqlScratch*/) /*const*/
|
||||
{
|
||||
return FB_NEW_POOL(getPool()) CumeDistWinNode(getPool());
|
||||
}
|
||||
|
||||
|
||||
//--------------------
|
||||
|
||||
|
||||
static WinFuncNode::RegisterFactory0<RowNumberWinNode> rowNumberWinInfo("ROW_NUMBER");
|
||||
|
||||
RowNumberWinNode::RowNumberWinNode(MemoryPool& pool)
|
||||
@ -238,13 +403,13 @@ void RowNumberWinNode::aggPass(thread_db* /*tdbb*/, jrd_req* /*request*/, dsc* /
|
||||
{
|
||||
}
|
||||
|
||||
dsc* RowNumberWinNode::aggExecute(thread_db* /*tdbb*/, jrd_req* request) const
|
||||
dsc* RowNumberWinNode::aggExecute(thread_db* /*tdbb*/, jrd_req* request, FB_UINT64 win_row_count) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
return &impure->vlu_desc;
|
||||
}
|
||||
|
||||
dsc* RowNumberWinNode::winPass(thread_db* /*tdbb*/, jrd_req* request, SlidingWindow* /*window*/) const
|
||||
dsc* RowNumberWinNode::winPass(thread_db* /*tdbb*/, jrd_req* request, SlidingWindow* /*window*/, FB_UINT64 /*win_row_count*/) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
++impure->vlu_misc.vlu_int64;
|
||||
@ -308,12 +473,12 @@ void FirstValueWinNode::aggPass(thread_db* /*tdbb*/, jrd_req* /*request*/, dsc*
|
||||
{
|
||||
}
|
||||
|
||||
dsc* FirstValueWinNode::aggExecute(thread_db* /*tdbb*/, jrd_req* /*request*/) const
|
||||
dsc* FirstValueWinNode::aggExecute(thread_db* /*tdbb*/, jrd_req* /*request*/, FB_UINT64 win_row_count) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dsc* FirstValueWinNode::winPass(thread_db* tdbb, jrd_req* request, SlidingWindow* window) const
|
||||
dsc* FirstValueWinNode::winPass(thread_db* tdbb, jrd_req* request, SlidingWindow* window, FB_UINT64 /*win_row_count*/) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
SINT64 records = impure->vlu_misc.vlu_int64++;
|
||||
@ -385,12 +550,12 @@ void LastValueWinNode::aggPass(thread_db* /*tdbb*/, jrd_req* /*request*/, dsc* /
|
||||
{
|
||||
}
|
||||
|
||||
dsc* LastValueWinNode::aggExecute(thread_db* /*tdbb*/, jrd_req* /*request*/) const
|
||||
dsc* LastValueWinNode::aggExecute(thread_db* /*tdbb*/, jrd_req* /*request*/, FB_UINT64 win_row_count) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dsc* LastValueWinNode::winPass(thread_db* tdbb, jrd_req* request, SlidingWindow* window) const
|
||||
dsc* LastValueWinNode::winPass(thread_db* tdbb, jrd_req* request, SlidingWindow* window, FB_UINT64 /*win_row_count*/) const
|
||||
{
|
||||
if (!window->move(0))
|
||||
return NULL;
|
||||
@ -472,12 +637,12 @@ void NthValueWinNode::aggPass(thread_db* /*tdbb*/, jrd_req* /*request*/, dsc* /*
|
||||
{
|
||||
}
|
||||
|
||||
dsc* NthValueWinNode::aggExecute(thread_db* /*tdbb*/, jrd_req* /*request*/) const
|
||||
dsc* NthValueWinNode::aggExecute(thread_db* /*tdbb*/, jrd_req* /*request*/, FB_UINT64 win_row_count) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dsc* NthValueWinNode::winPass(thread_db* tdbb, jrd_req* request, SlidingWindow* window) const
|
||||
dsc* NthValueWinNode::winPass(thread_db* tdbb, jrd_req* request, SlidingWindow* window, FB_UINT64 /*win_row_count*/) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
|
||||
@ -582,12 +747,12 @@ void LagLeadWinNode::aggPass(thread_db* /*tdbb*/, jrd_req* /*request*/, dsc* /*d
|
||||
{
|
||||
}
|
||||
|
||||
dsc* LagLeadWinNode::aggExecute(thread_db* /*tdbb*/, jrd_req* /*request*/) const
|
||||
dsc* LagLeadWinNode::aggExecute(thread_db* /*tdbb*/, jrd_req* /*request*/, FB_UINT64 win_row_count) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dsc* LagLeadWinNode::winPass(thread_db* tdbb, jrd_req* request, SlidingWindow* window) const
|
||||
dsc* LagLeadWinNode::winPass(thread_db* tdbb, jrd_req* request, SlidingWindow* window, FB_UINT64 /*win_row_count*/) const
|
||||
{
|
||||
window->move(0); // Come back to our row because rows may reference columns.
|
||||
|
||||
@ -679,4 +844,117 @@ AggNode* LeadWinNode::dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/
|
||||
}
|
||||
|
||||
|
||||
//--------------------
|
||||
|
||||
|
||||
static WinFuncNode::RegisterFactory0<NTileWinNode> nTileWinInfo("NTILE");
|
||||
|
||||
NTileWinNode::NTileWinNode(MemoryPool& pool, ValueExprNode* aArg)
|
||||
: WinFuncNode(pool, nTileWinInfo, aArg),
|
||||
tempImpure(0)
|
||||
{
|
||||
fb_assert(dsqlChildNodes.getCount() == 1 && jrdChildNodes.getCount() == 1);
|
||||
dsqlChildNodes.clear();
|
||||
jrdChildNodes.clear();
|
||||
addChildNode(arg, arg);
|
||||
}
|
||||
|
||||
void NTileWinNode::parseArgs(thread_db* tdbb, CompilerScratch* csb, unsigned /*count*/)
|
||||
{
|
||||
arg = PAR_parse_value(tdbb, csb);
|
||||
}
|
||||
|
||||
|
||||
string NTileWinNode::internalPrint(NodePrinter& printer) const
|
||||
{
|
||||
WinFuncNode::internalPrint(printer);
|
||||
|
||||
NODE_PRINT(printer, tempImpure);
|
||||
|
||||
return "NTileWinNode";
|
||||
}
|
||||
|
||||
void NTileWinNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc)
|
||||
{
|
||||
if (dsqlScratch->clientDialect == 1)
|
||||
desc->makeDouble();
|
||||
else
|
||||
desc->makeInt64(0);
|
||||
}
|
||||
|
||||
void NTileWinNode::getDesc(thread_db* /*tdbb*/, CompilerScratch* /*csb*/, dsc* desc)
|
||||
{
|
||||
desc->makeInt64(0);
|
||||
}
|
||||
|
||||
ValueExprNode* NTileWinNode::copy(thread_db* tdbb, NodeCopier& copier) const
|
||||
{
|
||||
NTileWinNode* node = FB_NEW_POOL(*tdbb->getDefaultPool()) NTileWinNode(*tdbb->getDefaultPool());
|
||||
node->arg = copier.copy(tdbb, arg);
|
||||
return node;
|
||||
}
|
||||
|
||||
AggNode* NTileWinNode::pass2(thread_db* tdbb, CompilerScratch* csb)
|
||||
{
|
||||
AggNode::pass2(tdbb, csb);
|
||||
tempImpure = CMP_impure(csb, sizeof(impure_value_ex));
|
||||
return this;
|
||||
}
|
||||
|
||||
void NTileWinNode::aggInit(thread_db* tdbb, jrd_req* request) const
|
||||
{
|
||||
AggNode::aggInit(tdbb, request);
|
||||
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
impure->make_int64(0, 0);
|
||||
impure->vlux_count = 0;
|
||||
}
|
||||
|
||||
void NTileWinNode::aggPass(thread_db* /*tdbb*/, jrd_req* request, dsc* /*desc*/) const
|
||||
{
|
||||
}
|
||||
|
||||
dsc* NTileWinNode::aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 /*win_row_count*/) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
return &impure->vlu_desc;
|
||||
}
|
||||
|
||||
dsc* NTileWinNode::winPass(thread_db* tdbb, jrd_req* request, SlidingWindow* window, FB_UINT64 win_row_count) const
|
||||
{
|
||||
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||
window->move(0); // Come back to our row because row may reference columns.
|
||||
dsc* desc = EVL_expr(tdbb, request, arg);
|
||||
if (!desc || (request->req_flags & req_null))
|
||||
status_exception::raise(Arg::Gds(isc_sysf_argnmustbe_positive) <<
|
||||
Arg::Num(1) << Arg::Str(aggInfo.name));
|
||||
|
||||
SINT64 buckets = MOV_get_int64(desc, 0);
|
||||
if (buckets <= 0)
|
||||
{
|
||||
status_exception::raise(Arg::Gds(isc_sysf_argnmustbe_positive) <<
|
||||
Arg::Num(1) << Arg::Str(aggInfo.name));
|
||||
}
|
||||
|
||||
SINT64 n = impure->vlux_count;
|
||||
|
||||
SINT64 top_boundary = win_row_count / buckets + 1;
|
||||
SINT64 bottom_boundary = win_row_count / buckets;
|
||||
SINT64 num_top_boundary = win_row_count % buckets;
|
||||
if (n < top_boundary * num_top_boundary)
|
||||
impure->vlu_misc.vlu_int64 = (n / top_boundary) + 1;
|
||||
else
|
||||
impure->vlu_misc.vlu_int64 = num_top_boundary + (n - num_top_boundary * top_boundary) / bottom_boundary + 1;
|
||||
|
||||
++impure->vlux_count;
|
||||
return &impure->vlu_desc;
|
||||
}
|
||||
|
||||
|
||||
AggNode* NTileWinNode::dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/
|
||||
{
|
||||
return FB_NEW_POOL(getPool()) NTileWinNode(getPool(), doDsqlPass(dsqlScratch, arg));
|
||||
}
|
||||
|
||||
|
||||
} // namespace Jrd
|
||||
|
@ -43,7 +43,7 @@ public:
|
||||
|
||||
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const;
|
||||
|
||||
protected:
|
||||
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
|
||||
@ -63,7 +63,53 @@ public:
|
||||
|
||||
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const;
|
||||
|
||||
protected:
|
||||
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
|
||||
|
||||
private:
|
||||
USHORT tempImpure;
|
||||
};
|
||||
|
||||
// PERCENT_RANK function.
|
||||
class PercentRankWinNode : public WinFuncNode
|
||||
{
|
||||
public:
|
||||
explicit PercentRankWinNode(MemoryPool& pool);
|
||||
|
||||
virtual Firebird::string internalPrint(NodePrinter& printer) const;
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier) const;
|
||||
virtual AggNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
|
||||
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const;
|
||||
|
||||
protected:
|
||||
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
|
||||
|
||||
private:
|
||||
USHORT tempImpure;
|
||||
};
|
||||
|
||||
// CUME_DIST function.
|
||||
class CumeDistWinNode : public WinFuncNode
|
||||
{
|
||||
public:
|
||||
explicit CumeDistWinNode(MemoryPool& pool);
|
||||
|
||||
virtual Firebird::string internalPrint(NodePrinter& printer) const;
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier) const;
|
||||
virtual AggNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
|
||||
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const;
|
||||
|
||||
protected:
|
||||
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
|
||||
@ -85,14 +131,14 @@ public:
|
||||
|
||||
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const;
|
||||
|
||||
virtual bool shouldCallWinPass() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual dsc* winPass(thread_db* tdbb, jrd_req* request, SlidingWindow* window) const;
|
||||
virtual dsc* winPass(thread_db* tdbb, jrd_req* request, SlidingWindow* window, FB_UINT64 /*win_rou_count*/) const;
|
||||
|
||||
protected:
|
||||
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
|
||||
@ -111,14 +157,14 @@ public:
|
||||
|
||||
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const;
|
||||
|
||||
virtual bool shouldCallWinPass() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual dsc* winPass(thread_db* tdbb, jrd_req* request, SlidingWindow* window) const;
|
||||
virtual dsc* winPass(thread_db* tdbb, jrd_req* request, SlidingWindow* window, FB_UINT64 /*win_rou_count*/) const;
|
||||
|
||||
protected:
|
||||
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
|
||||
@ -139,14 +185,14 @@ public:
|
||||
|
||||
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const;
|
||||
|
||||
virtual bool shouldCallWinPass() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual dsc* winPass(thread_db* tdbb, jrd_req* request, SlidingWindow* window) const;
|
||||
virtual dsc* winPass(thread_db* tdbb, jrd_req* request, SlidingWindow* window, FB_UINT64 /*win_rou_count*/) const;
|
||||
|
||||
protected:
|
||||
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
|
||||
@ -175,14 +221,14 @@ public:
|
||||
|
||||
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const;
|
||||
|
||||
virtual bool shouldCallWinPass() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual dsc* winPass(thread_db* tdbb, jrd_req* request, SlidingWindow* window) const;
|
||||
virtual dsc* winPass(thread_db* tdbb, jrd_req* request, SlidingWindow* window, FB_UINT64 /*win_rou_count*/) const;
|
||||
|
||||
protected:
|
||||
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
|
||||
@ -207,14 +253,14 @@ public:
|
||||
|
||||
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const;
|
||||
|
||||
virtual bool shouldCallWinPass() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual dsc* winPass(thread_db* tdbb, jrd_req* request, SlidingWindow* window) const;
|
||||
virtual dsc* winPass(thread_db* tdbb, jrd_req* request, SlidingWindow* window, FB_UINT64 /*win_rou_count*/) const;
|
||||
|
||||
protected:
|
||||
virtual void parseArgs(thread_db* tdbb, CompilerScratch* csb, unsigned count);
|
||||
@ -263,6 +309,36 @@ protected:
|
||||
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
|
||||
};
|
||||
|
||||
// NTILE function.
|
||||
class NTileWinNode : public WinFuncNode
|
||||
{
|
||||
public:
|
||||
explicit NTileWinNode(MemoryPool& pool, ValueExprNode* aArg = NULL);
|
||||
|
||||
virtual Firebird::string internalPrint(NodePrinter& printer) const;
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier) const;
|
||||
virtual AggNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
|
||||
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
|
||||
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
|
||||
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request, FB_UINT64 win_row_count) const;
|
||||
virtual bool shouldCallWinPass() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual dsc* winPass(thread_db* tdbb, jrd_req* request, SlidingWindow* window, FB_UINT64 /*win_rou_count*/) const;
|
||||
|
||||
protected:
|
||||
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
|
||||
virtual void parseArgs(thread_db* tdbb, CompilerScratch* csb, unsigned count);
|
||||
|
||||
private:
|
||||
USHORT tempImpure;
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
@ -589,6 +589,12 @@ using namespace Firebird;
|
||||
%token <metaNamePtr> REGR_SXY
|
||||
%token <metaNamePtr> REGR_SYY
|
||||
|
||||
// tokens added for Firebird 4.0
|
||||
|
||||
%token <metaNamePtr> PERCENT_RANK
|
||||
%token <metaNamePtr> CUME_DIST
|
||||
%token <metaNamePtr> NTILE
|
||||
|
||||
// precedence declarations for expression evaluation
|
||||
|
||||
%left OR
|
||||
@ -6945,6 +6951,10 @@ window_function
|
||||
{ $$ = newNode<DenseRankWinNode>(); }
|
||||
| RANK '(' ')'
|
||||
{ $$ = newNode<RankWinNode>(); }
|
||||
| PERCENT_RANK '(' ')'
|
||||
{ $$ = newNode<PercentRankWinNode>(); }
|
||||
| CUME_DIST '(' ')'
|
||||
{ $$ = newNode<CumeDistWinNode>(); }
|
||||
| ROW_NUMBER '(' ')'
|
||||
{ $$ = newNode<RowNumberWinNode>(); }
|
||||
| FIRST_VALUE '(' value ')'
|
||||
@ -6965,6 +6975,8 @@ window_function
|
||||
{ $$ = newNode<LeadWinNode>($3, $5, newNode<NullNode>()); }
|
||||
| LEAD '(' value ')'
|
||||
{ $$ = newNode<LeadWinNode>($3, MAKE_const_slong(1), newNode<NullNode>()); }
|
||||
| NTILE '(' u_numeric_constant ')'
|
||||
{ $$ = newNode<NTileWinNode>($3); }
|
||||
;
|
||||
|
||||
%type <valueExprNode> nth_from
|
||||
@ -7774,7 +7786,10 @@ non_reserved_word
|
||||
| LAST_VALUE
|
||||
| LAG
|
||||
| LEAD
|
||||
| NTILE
|
||||
| RANK
|
||||
| PERCENT_RANK
|
||||
| CUME_DIST
|
||||
| ROW_NUMBER
|
||||
| USAGE
|
||||
| LINGER
|
||||
|
@ -125,6 +125,8 @@ bool AggregatedStream::getRecord(thread_db* tdbb) const
|
||||
if (m_bufferedStream) // Is that a window stream?
|
||||
{
|
||||
const FB_UINT64 position = m_bufferedStream->getPosition(request);
|
||||
FB_UINT64 win_row_count = m_bufferedStream->getCount(tdbb);
|
||||
m_bufferedStream->locate(tdbb, position);
|
||||
|
||||
if (impure->pending == 0)
|
||||
{
|
||||
@ -134,7 +136,7 @@ bool AggregatedStream::getRecord(thread_db* tdbb) const
|
||||
fb_assert(false);
|
||||
}
|
||||
|
||||
impure->state = evaluateGroup(tdbb, impure->state);
|
||||
impure->state = evaluateGroup(tdbb, impure->state, win_row_count);
|
||||
|
||||
if (impure->state == STATE_PROCESS_EOF)
|
||||
{
|
||||
@ -165,7 +167,7 @@ bool AggregatedStream::getRecord(thread_db* tdbb) const
|
||||
const USHORT id = field->fieldId;
|
||||
Record* record = request->req_rpb[field->fieldStream].rpb_record;
|
||||
|
||||
desc = aggNode->winPass(tdbb, request, &window);
|
||||
desc = aggNode->winPass(tdbb, request, &window, win_row_count);
|
||||
|
||||
if (!desc)
|
||||
record->setNull(id);
|
||||
@ -205,7 +207,7 @@ bool AggregatedStream::getRecord(thread_db* tdbb) const
|
||||
}
|
||||
else
|
||||
{
|
||||
impure->state = evaluateGroup(tdbb, impure->state);
|
||||
impure->state = evaluateGroup(tdbb, impure->state, 0);
|
||||
|
||||
if (impure->state == STATE_PROCESS_EOF)
|
||||
{
|
||||
@ -295,7 +297,7 @@ void AggregatedStream::init(thread_db* tdbb, CompilerScratch* csb)
|
||||
|
||||
// Compute the next aggregated record of a value group. evlGroup is driven by, and returns, a state
|
||||
// variable.
|
||||
AggregatedStream::State AggregatedStream::evaluateGroup(thread_db* tdbb, State state) const
|
||||
AggregatedStream::State AggregatedStream::evaluateGroup(thread_db* tdbb, State state, FB_UINT64 win_row_count) const
|
||||
{
|
||||
jrd_req* const request = tdbb->getRequest();
|
||||
|
||||
@ -414,7 +416,7 @@ AggregatedStream::State AggregatedStream::evaluateGroup(thread_db* tdbb, State s
|
||||
const USHORT id = field->fieldId;
|
||||
Record* record = request->req_rpb[field->fieldStream].rpb_record;
|
||||
|
||||
dsc* desc = aggNode->execute(tdbb, request);
|
||||
dsc* desc = aggNode->execute(tdbb, request, win_row_count);
|
||||
if (!desc || !desc->dsc_dtype)
|
||||
record->setNull(id);
|
||||
else
|
||||
|
@ -661,7 +661,7 @@ namespace Jrd
|
||||
private:
|
||||
void init(thread_db* tdbb, CompilerScratch* csb);
|
||||
|
||||
State evaluateGroup(thread_db* tdbb, State state) const;
|
||||
State evaluateGroup(thread_db* tdbb, State state, FB_UINT64 win_row_count) const;
|
||||
void cacheValues(thread_db* tdbb, jrd_req* request,
|
||||
const NestValueArray* group, unsigned impureOffset) const;
|
||||
bool lookForChange(thread_db* tdbb, jrd_req* request,
|
||||
|
@ -139,6 +139,7 @@ static const TOK tokens[] =
|
||||
{CREATE, "CREATE", 1, false},
|
||||
{CROSS, "CROSS", 2, false},
|
||||
{CSTRING, "CSTRING", 1, false},
|
||||
{CUME_DIST, "CUME_DIST", 2, false},
|
||||
{CURRENT, "CURRENT", 1, false},
|
||||
{CURRENT_CONNECTION, "CURRENT_CONNECTION", 2, false},
|
||||
{CURRENT_DATE, "CURRENT_DATE", 2, false},
|
||||
@ -280,6 +281,7 @@ static const TOK tokens[] =
|
||||
{NO, "NO", 1, false},
|
||||
{NOT, "NOT", 1, false},
|
||||
{NTH_VALUE, "NTH_VALUE", 2, false},
|
||||
{NTILE, "NTILE", 2, false},
|
||||
{NULLIF, "NULLIF", 2, true},
|
||||
{KW_NULL, "NULL", 1, false},
|
||||
{NULLS, "NULLS", 2, true},
|
||||
@ -307,6 +309,7 @@ static const TOK tokens[] =
|
||||
{PARAMETER, "PARAMETER", 1, false},
|
||||
{PARTITION, "PARTITION", 2, false},
|
||||
{PASSWORD, "PASSWORD", 1, false},
|
||||
{PERCENT_RANK, "PERCENT_RANK", 2, false},
|
||||
{PI, "PI", 2, false},
|
||||
{PLACING, "PLACING", 2, false},
|
||||
{PLAN, "PLAN", 1, false},
|
||||
|
Loading…
Reference in New Issue
Block a user