mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 16:43:03 +01:00
SQL 2023 ANY_VALUE aggregate function. (#7617)
This commit is contained in:
parent
fa9c6d4d3c
commit
986e96fac8
24
doc/sql.extensions/README.aggregate_functions.md
Normal file
24
doc/sql.extensions/README.aggregate_functions.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Aggregate Functions
|
||||||
|
|
||||||
|
|
||||||
|
## ANY_VALUE (Firebird 6.0)
|
||||||
|
|
||||||
|
`ANY_VALUE` is a non-deterministic aggregate function that returns its expression for an arbitrary
|
||||||
|
record from the grouped rows.
|
||||||
|
|
||||||
|
`NULLs` are ignored. It's returned only in the case of none evaluated records having a non-null value.
|
||||||
|
|
||||||
|
Syntax:
|
||||||
|
|
||||||
|
```
|
||||||
|
<any value> ::= ANY_VALUE(<expression>)
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
select department,
|
||||||
|
any_value(employee) employee
|
||||||
|
from employee_department
|
||||||
|
group by department
|
||||||
|
```
|
@ -62,6 +62,7 @@ PARSER_TOKEN(TOK_AFTER, "AFTER", true)
|
|||||||
PARSER_TOKEN(TOK_ALL, "ALL", false)
|
PARSER_TOKEN(TOK_ALL, "ALL", false)
|
||||||
PARSER_TOKEN(TOK_ALTER, "ALTER", false)
|
PARSER_TOKEN(TOK_ALTER, "ALTER", false)
|
||||||
PARSER_TOKEN(TOK_ALWAYS, "ALWAYS", true)
|
PARSER_TOKEN(TOK_ALWAYS, "ALWAYS", true)
|
||||||
|
PARSER_TOKEN(TOK_ANY_VALUE, "ANY_VALUE", true)
|
||||||
PARSER_TOKEN(TOK_AND, "AND", false)
|
PARSER_TOKEN(TOK_AND, "AND", false)
|
||||||
PARSER_TOKEN(TOK_ANY, "ANY", false)
|
PARSER_TOKEN(TOK_ANY, "ANY", false)
|
||||||
PARSER_TOKEN(TOK_AS, "AS", false)
|
PARSER_TOKEN(TOK_AS, "AS", false)
|
||||||
|
@ -491,6 +491,92 @@ dsc* AggNode::execute(thread_db* tdbb, Request* request) const
|
|||||||
//--------------------
|
//--------------------
|
||||||
|
|
||||||
|
|
||||||
|
static AggNode::RegisterFactory0<AnyValueAggNode> anyValueAggInfo("ANY_VALUE");
|
||||||
|
|
||||||
|
AnyValueAggNode::AnyValueAggNode(MemoryPool& pool, ValueExprNode* aArg)
|
||||||
|
: AggNode(pool, anyValueAggInfo, false, false, aArg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DmlNode* AnyValueAggNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, const UCHAR /*blrOp*/)
|
||||||
|
{
|
||||||
|
const auto node = FB_NEW_POOL(pool) AnyValueAggNode(pool);
|
||||||
|
node->arg = PAR_parse_value(tdbb, csb);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnyValueAggNode::parseArgs(thread_db* tdbb, CompilerScratch* csb, unsigned /*count*/)
|
||||||
|
{
|
||||||
|
arg = PAR_parse_value(tdbb, csb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnyValueAggNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc)
|
||||||
|
{
|
||||||
|
DsqlDescMaker::fromNode(dsqlScratch, desc, arg, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnyValueAggNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
|
||||||
|
{
|
||||||
|
arg->getDesc(tdbb, csb, desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueExprNode* AnyValueAggNode::copy(thread_db* tdbb, NodeCopier& copier) const
|
||||||
|
{
|
||||||
|
const auto node = FB_NEW_POOL(*tdbb->getDefaultPool()) AnyValueAggNode(*tdbb->getDefaultPool());
|
||||||
|
node->nodScale = nodScale;
|
||||||
|
node->arg = copier.copy(tdbb, arg);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
string AnyValueAggNode::internalPrint(NodePrinter& printer) const
|
||||||
|
{
|
||||||
|
AggNode::internalPrint(printer);
|
||||||
|
|
||||||
|
return "AnyValueAggNode";
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnyValueAggNode::aggInit(thread_db* tdbb, Request* request) const
|
||||||
|
{
|
||||||
|
AggNode::aggInit(tdbb, request);
|
||||||
|
|
||||||
|
const auto impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||||
|
impure->vlu_desc.dsc_dtype = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnyValueAggNode::aggPass(thread_db* tdbb, Request* request, dsc* desc) const
|
||||||
|
{
|
||||||
|
const auto impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||||
|
|
||||||
|
if (!impure->vlu_desc.dsc_dtype)
|
||||||
|
{
|
||||||
|
const auto argValue = EVL_expr(tdbb, request, arg);
|
||||||
|
|
||||||
|
if (!(request->req_flags & req_null))
|
||||||
|
EVL_make_value(tdbb, argValue, impure);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
dsc* AnyValueAggNode::aggExecute(thread_db* /*tdbb*/, Request* request) const
|
||||||
|
{
|
||||||
|
const auto impure = request->getImpure<impure_value_ex>(impureOffset);
|
||||||
|
|
||||||
|
if (impure->vlu_desc.dsc_dtype)
|
||||||
|
return &impure->vlu_desc;
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
AggNode* AnyValueAggNode::dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/
|
||||||
|
{
|
||||||
|
return FB_NEW_POOL(dsqlScratch->getPool()) AnyValueAggNode(dsqlScratch->getPool(),
|
||||||
|
doDsqlPass(dsqlScratch, arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------
|
||||||
|
|
||||||
|
|
||||||
static AggNode::Register<AvgAggNode> avgAggInfo("AVG", blr_agg_average, blr_agg_average_distinct);
|
static AggNode::Register<AvgAggNode> avgAggInfo("AVG", blr_agg_average, blr_agg_average_distinct);
|
||||||
|
|
||||||
AvgAggNode::AvgAggNode(MemoryPool& pool, bool aDistinct, bool aDialect1, ValueExprNode* aArg)
|
AvgAggNode::AvgAggNode(MemoryPool& pool, bool aDistinct, bool aDialect1, ValueExprNode* aArg)
|
||||||
|
@ -30,6 +30,33 @@
|
|||||||
namespace Jrd {
|
namespace Jrd {
|
||||||
|
|
||||||
|
|
||||||
|
class AnyValueAggNode final : public AggNode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit AnyValueAggNode(MemoryPool& pool, ValueExprNode* aArg = nullptr);
|
||||||
|
|
||||||
|
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, const UCHAR blrOp);
|
||||||
|
|
||||||
|
unsigned getCapabilities() const override
|
||||||
|
{
|
||||||
|
return CAP_RESPECTS_WINDOW_FRAME | CAP_WANTS_AGG_CALLS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void parseArgs(thread_db* tdbb, CompilerScratch* csb, unsigned count) override;
|
||||||
|
|
||||||
|
Firebird::string internalPrint(NodePrinter& printer) const override;
|
||||||
|
void make(DsqlCompilerScratch* dsqlScratch, dsc* desc) override;
|
||||||
|
void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc) override;
|
||||||
|
ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier) const override;
|
||||||
|
|
||||||
|
void aggInit(thread_db* tdbb, Request* request) const override;
|
||||||
|
void aggPass(thread_db* tdbb, Request* request, dsc* desc) const override;
|
||||||
|
dsc* aggExecute(thread_db* tdbb, Request* request) const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/ override;
|
||||||
|
};
|
||||||
|
|
||||||
class AvgAggNode final : public AggNode
|
class AvgAggNode final : public AggNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -696,6 +696,10 @@ using namespace Firebird;
|
|||||||
%token <metaNamePtr> UNICODE_CHAR
|
%token <metaNamePtr> UNICODE_CHAR
|
||||||
%token <metaNamePtr> UNICODE_VAL
|
%token <metaNamePtr> UNICODE_VAL
|
||||||
|
|
||||||
|
// tokens added for Firebird 6.0
|
||||||
|
|
||||||
|
%token <metaNamePtr> ANY_VALUE
|
||||||
|
|
||||||
// precedence declarations for expression evaluation
|
// precedence declarations for expression evaluation
|
||||||
|
|
||||||
%left OR
|
%left OR
|
||||||
@ -8029,6 +8033,8 @@ aggregate_function_prefix
|
|||||||
{ $$ = newNode<RegrAggNode>(RegrAggNode::TYPE_REGR_SXY, $3, $5); }
|
{ $$ = newNode<RegrAggNode>(RegrAggNode::TYPE_REGR_SXY, $3, $5); }
|
||||||
| REGR_SYY '(' value ',' value ')'
|
| REGR_SYY '(' value ',' value ')'
|
||||||
{ $$ = newNode<RegrAggNode>(RegrAggNode::TYPE_REGR_SYY, $3, $5); }
|
{ $$ = newNode<RegrAggNode>(RegrAggNode::TYPE_REGR_SYY, $3, $5); }
|
||||||
|
| ANY_VALUE '(' distinct_noise value ')'
|
||||||
|
{ $$ = newNode<AnyValueAggNode>($4); }
|
||||||
;
|
;
|
||||||
|
|
||||||
%type <aggNode> window_function
|
%type <aggNode> window_function
|
||||||
@ -9225,6 +9231,8 @@ non_reserved_word
|
|||||||
| TIMEZONE_NAME
|
| TIMEZONE_NAME
|
||||||
| UNICODE_CHAR
|
| UNICODE_CHAR
|
||||||
| UNICODE_VAL
|
| UNICODE_VAL
|
||||||
|
// added in FB 6.0
|
||||||
|
| ANY_VALUE
|
||||||
;
|
;
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
Loading…
Reference in New Issue
Block a user