mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 17:23:03 +01:00
Merge branch 'new_window_functions' of git://github.com/nakagami/firebird into new-window-functions
This commit is contained in:
commit
26895605f4
@ -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
|
||||
--------------------------
|
||||
|
@ -430,7 +430,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);
|
||||
|
||||
@ -469,7 +469,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;
|
||||
}
|
||||
|
||||
|
||||
@ -664,7 +671,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);
|
||||
|
||||
@ -815,7 +822,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);
|
||||
|
||||
@ -928,7 +935,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);
|
||||
|
||||
@ -1172,7 +1179,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);
|
||||
|
||||
@ -1269,7 +1276,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);
|
||||
|
||||
@ -1382,7 +1389,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);
|
||||
@ -1548,7 +1555,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);
|
||||
@ -1740,7 +1747,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);
|
||||
@ -1904,7 +1911,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, AggType aggType) 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, AggType aggType) 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, AggType aggType) 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, AggType aggType) 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, AggType aggType) 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, AggType aggType) 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, AggType aggType) 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, AggType aggType) 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, AggType aggType) 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*/;
|
||||
|
@ -973,7 +973,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@ -982,9 +982,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);
|
||||
|
||||
|
@ -94,7 +94,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);
|
||||
|
||||
@ -178,7 +178,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);
|
||||
|
||||
@ -203,6 +203,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)
|
||||
@ -252,13 +417,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;
|
||||
@ -325,12 +490,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++;
|
||||
@ -402,12 +567,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;
|
||||
@ -492,12 +657,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);
|
||||
|
||||
@ -602,12 +767,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.
|
||||
|
||||
@ -699,4 +864,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, AggType aggType) 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, AggType aggType) 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, AggType aggType) 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 void aggSetup(bool& wantWinPass) const
|
||||
{
|
||||
wantWinPass = 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, AggType aggType) 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 void aggSetup(bool& wantWinPass) const
|
||||
{
|
||||
wantWinPass = 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, AggType aggType) 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 void aggSetup(bool& wantWinPass) const
|
||||
{
|
||||
wantWinPass = 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, AggType aggType) 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 void aggSetup(bool& wantWinPass) const
|
||||
{
|
||||
wantWinPass = 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, AggType aggType) 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 void aggSetup(bool& wantWinPass) const
|
||||
{
|
||||
wantWinPass = 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
|
||||
|
||||
|
@ -591,6 +591,9 @@ using namespace Firebird;
|
||||
|
||||
// tokens added for Firebird 4.0
|
||||
|
||||
%token <metaNamePtr> CUME_DIST
|
||||
%token <metaNamePtr> NTILE
|
||||
%token <metaNamePtr> PERCENT_RANK
|
||||
%token <metaNamePtr> PRIVILEGE
|
||||
%token <metaNamePtr> RDB_ROLE_IN_USE
|
||||
%token <metaNamePtr> RDB_SYSTEM_PRIVILEGE
|
||||
@ -7000,6 +7003,10 @@ window_function
|
||||
{ $$ = newNode<DenseRankWinNode>(); }
|
||||
| RANK '(' ')'
|
||||
{ $$ = newNode<RankWinNode>(); }
|
||||
| PERCENT_RANK '(' ')'
|
||||
{ $$ = newNode<PercentRankWinNode>(); }
|
||||
| CUME_DIST '(' ')'
|
||||
{ $$ = newNode<CumeDistWinNode>(); }
|
||||
| ROW_NUMBER '(' ')'
|
||||
{ $$ = newNode<RowNumberWinNode>(); }
|
||||
| FIRST_VALUE '(' value ')'
|
||||
@ -7020,6 +7027,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
|
||||
@ -7835,7 +7844,10 @@ non_reserved_word
|
||||
| LAST_VALUE
|
||||
| LAG
|
||||
| LEAD
|
||||
| NTILE
|
||||
| RANK
|
||||
| PERCENT_RANK
|
||||
| CUME_DIST
|
||||
| ROW_NUMBER
|
||||
| USAGE
|
||||
| LINGER
|
||||
|
@ -139,6 +139,7 @@ static const TOK tokens[] =
|
||||
{CREATE, "CREATE", false},
|
||||
{CROSS, "CROSS", false},
|
||||
{CSTRING, "CSTRING", false},
|
||||
{CUME_DIST, "CUME_DIST", false},
|
||||
{CURRENT, "CURRENT", false},
|
||||
{CURRENT_CONNECTION, "CURRENT_CONNECTION", false},
|
||||
{CURRENT_DATE, "CURRENT_DATE", false},
|
||||
@ -280,6 +281,7 @@ static const TOK tokens[] =
|
||||
{NO, "NO", false},
|
||||
{NOT, "NOT", false},
|
||||
{NTH_VALUE, "NTH_VALUE", false},
|
||||
{NTILE, "NTILE", false},
|
||||
{NULLIF, "NULLIF", true},
|
||||
{KW_NULL, "NULL", false},
|
||||
{NULLS, "NULLS", true},
|
||||
@ -307,6 +309,7 @@ static const TOK tokens[] =
|
||||
{PARAMETER, "PARAMETER", false},
|
||||
{PARTITION, "PARTITION", false},
|
||||
{PASSWORD, "PASSWORD", false},
|
||||
{PERCENT_RANK, "PERCENT_RANK", false},
|
||||
{PI, "PI", false},
|
||||
{PLACING, "PLACING", false},
|
||||
{PLAN, "PLAN", false},
|
||||
|
Loading…
Reference in New Issue
Block a user