8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 16:43:03 +01:00

Feature #7566 - Allow DEFAULT keyword in argument list.

This commit is contained in:
Adriano dos Santos Fernandes 2023-09-19 07:19:19 -03:00
parent 5dbd5a46ef
commit 00a50429cb
12 changed files with 56 additions and 23 deletions

View File

@ -30,13 +30,18 @@ named arguments.
[ {<positional arguments>,} ] <named arguments> [ {<positional arguments>,} ] <named arguments>
<positional arguments> ::= <positional arguments> ::=
<value> [ {, <value>}... ] <value or default> [ {, <value or default>}... ]
<named arguments> ::= <named arguments> ::=
<named argument> [ {, <named argument>}... ] <named argument> [ {, <named argument>}... ]
<named argument> ::= <named argument> ::=
<argument name> => <value> <argument name> => <value or default>
<value or default> ::=
<value> |
DEFAULT
``` ```
## Examples ## Examples
@ -51,6 +56,11 @@ select function_name(1, parameter2 => 'Two')
from rdb$database from rdb$database
``` ```
```
select function_name(default, parameter2 => 'Two')
from rdb$database
```
``` ```
execute procedure insert_customer( execute procedure insert_customer(
last_name => 'SCHUMACHER', last_name => 'SCHUMACHER',

View File

@ -13087,12 +13087,15 @@ DmlNode* UdfCallNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
for (auto& parameter : node->function->getInputFields()) for (auto& parameter : node->function->getInputFields())
{ {
if (const auto argValue = argsByName.get(parameter->prm_name)) const auto argValue = argsByName.get(parameter->prm_name);
if (argValue)
{ {
*argIt = *argValue; *argIt = *argValue;
argsByName.remove(parameter->prm_name); argsByName.remove(parameter->prm_name);
} }
else
if (!argValue || !*argValue)
{ {
if (parameter->prm_default_value) if (parameter->prm_default_value)
*argIt = CMP_clone_node(tdbb, csb, parameter->prm_default_value); *argIt = CMP_clone_node(tdbb, csb, parameter->prm_default_value);
@ -13185,7 +13188,7 @@ void UdfCallNode::genBlr(DsqlCompilerScratch* dsqlScratch)
dsqlScratch->appendUShort(args->items.getCount()); dsqlScratch->appendUShort(args->items.getCount());
for (auto& arg : args->items) for (auto& arg : args->items)
GEN_expr(dsqlScratch, arg); GEN_arg(dsqlScratch, arg);
dsqlScratch->appendUChar(blr_end); dsqlScratch->appendUChar(blr_end);
@ -13204,7 +13207,7 @@ void UdfCallNode::genBlr(DsqlCompilerScratch* dsqlScratch)
dsqlScratch->appendUChar(args->items.getCount()); dsqlScratch->appendUChar(args->items.getCount());
for (auto& arg : args->items) for (auto& arg : args->items)
GEN_expr(dsqlScratch, arg); GEN_arg(dsqlScratch, arg);
} }
void UdfCallNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc) void UdfCallNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc)

View File

@ -3430,7 +3430,7 @@ void ExecProcedureNode::genBlr(DsqlCompilerScratch* dsqlScratch)
dsqlScratch->appendUShort(inputSources->items.getCount()); dsqlScratch->appendUShort(inputSources->items.getCount());
for (auto& arg : inputSources->items) for (auto& arg : inputSources->items)
GEN_expr(dsqlScratch, arg); GEN_arg(dsqlScratch, arg);
} }
// Output parameters. // Output parameters.
@ -3461,11 +3461,9 @@ void ExecProcedureNode::genBlr(DsqlCompilerScratch* dsqlScratch)
if (inputSources) if (inputSources)
{ {
dsqlScratch->appendUShort(inputSources->items.getCount()); dsqlScratch->appendUShort(inputSources->items.getCount());
auto ptr = inputSources->items.begin();
const auto end = inputSources->items.end();
while (ptr < end) for (auto& arg : inputSources->items)
GEN_expr(dsqlScratch, *ptr++); GEN_arg(dsqlScratch, arg);
} }
else else
dsqlScratch->appendUShort(0); dsqlScratch->appendUShort(0);
@ -3474,10 +3472,9 @@ void ExecProcedureNode::genBlr(DsqlCompilerScratch* dsqlScratch)
if (outputSources) if (outputSources)
{ {
dsqlScratch->appendUShort(outputSources->items.getCount()); dsqlScratch->appendUShort(outputSources->items.getCount());
auto ptr = outputSources->items.begin();
for (const auto end = outputSources->items.end(); ptr != end; ++ptr) for (auto& arg : outputSources->items)
GEN_expr(dsqlScratch, *ptr); GEN_expr(dsqlScratch, arg);
} }
else else
dsqlScratch->appendUShort(0); dsqlScratch->appendUShort(0);

View File

@ -65,6 +65,17 @@ using namespace Firebird;
static void gen_plan(DsqlCompilerScratch*, const PlanNode*); static void gen_plan(DsqlCompilerScratch*, const PlanNode*);
// Generate blr for an argument.
// When it is nullptr, generate blr_default_arg.
void GEN_arg(DsqlCompilerScratch* dsqlScratch, ExprNode* node)
{
if (node)
GEN_expr(dsqlScratch, node);
else
dsqlScratch->appendUChar(blr_default_arg);
}
void GEN_hidden_variables(DsqlCompilerScratch* dsqlScratch) void GEN_hidden_variables(DsqlCompilerScratch* dsqlScratch)
{ {
/************************************** /**************************************

View File

@ -30,6 +30,7 @@ namespace Jrd
class ValueListNode; class ValueListNode;
} }
void GEN_arg(Jrd::DsqlCompilerScratch*, Jrd::ExprNode*);
void GEN_descriptor(Jrd::DsqlCompilerScratch* dsqlScratch, const dsc* desc, bool texttype); void GEN_descriptor(Jrd::DsqlCompilerScratch* dsqlScratch, const dsc* desc, bool texttype);
void GEN_expr(Jrd::DsqlCompilerScratch*, Jrd::ExprNode*); void GEN_expr(Jrd::DsqlCompilerScratch*, Jrd::ExprNode*);
void GEN_hidden_variables(Jrd::DsqlCompilerScratch* dsqlScratch); void GEN_hidden_variables(Jrd::DsqlCompilerScratch* dsqlScratch);

View File

@ -8618,12 +8618,12 @@ argument_list_opt
%type <namedArguments> argument_list %type <namedArguments> argument_list
argument_list argument_list
: named_argument_list : named_argument_list
| value_list | value_or_default_list
{ {
$$ = newNode<NonPooledPair<ObjectsArray<MetaName>*, ValueListNode*>>(); $$ = newNode<NonPooledPair<ObjectsArray<MetaName>*, ValueListNode*>>();
$$->second = $1; $$->second = $1;
} }
| value_list ',' named_argument_list | value_or_default_list ',' named_argument_list
{ {
$$ = $3; $$ = $3;
@ -8655,7 +8655,7 @@ named_argument_list
%type <namedArgument> named_argument %type <namedArgument> named_argument
named_argument named_argument
: symbol_column_name NAMED_ARG_ASSIGN value : symbol_column_name NAMED_ARG_ASSIGN value_or_default
{ $$ = newNode<NonPooledPair<MetaName*, ValueExprNode*>>($1, $3); } { $$ = newNode<NonPooledPair<MetaName*, ValueExprNode*>>($1, $3); }
; ;

View File

@ -492,4 +492,6 @@
#define blr_invsel_procedure_context (unsigned char) 6 #define blr_invsel_procedure_context (unsigned char) 6
#define blr_invsel_procedure_alias (unsigned char) 7 #define blr_invsel_procedure_alias (unsigned char) 7
#define blr_default_arg (unsigned char) 227
#endif // FIREBIRD_IMPL_BLR_H #endif // FIREBIRD_IMPL_BLR_H

View File

@ -970,5 +970,5 @@ FB_IMPL_MSG(JRD, 967, idx_expr_not_found, -902, "42", "000", "Definition of inde
FB_IMPL_MSG(JRD, 968, idx_cond_not_found, -902, "42", "000", "Definition of index condition is not found for index @1") FB_IMPL_MSG(JRD, 968, idx_cond_not_found, -902, "42", "000", "Definition of index condition is not found for index @1")
FB_IMPL_MSG(JRD, 969, uninitialized_var, -625, "42", "000", "Variable @1 is not initialized") FB_IMPL_MSG(JRD, 969, uninitialized_var, -625, "42", "000", "Variable @1 is not initialized")
FB_IMPL_MSG(JRD, 970, param_not_exist, -170, "07", "001", "Parameter @1 does not exist") FB_IMPL_MSG(JRD, 970, param_not_exist, -170, "07", "001", "Parameter @1 does not exist")
FB_IMPL_MSG(JRD, 971, param_no_default_not_specified, -170, "07", "001", "Parameter @1 has no default value and was not specified") FB_IMPL_MSG(JRD, 971, param_no_default_not_specified, -170, "07", "001", "Parameter @1 has no default value and was not specified or was specified with DEFAULT")
FB_IMPL_MSG(JRD, 972, param_multiple_assignments, -170, "07", "001", "Parameter @1 has multiple assignments") FB_IMPL_MSG(JRD, 972, param_multiple_assignments, -170, "07", "001", "Parameter @1 has multiple assignments")

View File

@ -1294,7 +1294,7 @@ void ProcedureSourceNode::genBlr(DsqlCompilerScratch* dsqlScratch)
dsqlScratch->appendUShort(inputSources->items.getCount()); dsqlScratch->appendUShort(inputSources->items.getCount());
for (auto& arg : inputSources->items) for (auto& arg : inputSources->items)
GEN_expr(dsqlScratch, arg); GEN_arg(dsqlScratch, arg);
} }
if (dsqlContext->ctx_context > MAX_UCHAR) if (dsqlContext->ctx_context > MAX_UCHAR)
@ -1355,7 +1355,7 @@ void ProcedureSourceNode::genBlr(DsqlCompilerScratch* dsqlScratch)
dsqlScratch->appendUShort(inputSources->items.getCount()); dsqlScratch->appendUShort(inputSources->items.getCount());
for (auto& arg : inputSources->items) for (auto& arg : inputSources->items)
GEN_expr(dsqlScratch, arg); GEN_arg(dsqlScratch, arg);
} }
else else
dsqlScratch->appendUShort(0); dsqlScratch->appendUShort(0);

View File

@ -258,5 +258,6 @@ static const struct
{"invoke_function", invoke_function}, {"invoke_function", invoke_function},
{"invoke_procedure", invsel_procedure}, {"invoke_procedure", invsel_procedure},
{"select_procedure", invsel_procedure}, {"select_procedure", invsel_procedure},
{"blr_default_arg", zero},
{0, 0} {0, 0}
}; };

View File

@ -553,12 +553,15 @@ Arg::StatusVector CMP_procedure_arguments(
for (auto& parameter : fields) for (auto& parameter : fields)
{ {
if (const auto argValue = argsByName.get(parameter->prm_name)) const auto argValue = argsByName.get(parameter->prm_name);
if (argValue)
{ {
*sourceArgIt = *argValue; *sourceArgIt = *argValue;
argsByName.remove(parameter->prm_name); argsByName.remove(parameter->prm_name);
} }
else if (isInput)
if (isInput && (!argValue || !*argValue))
{ {
if (parameter->prm_default_value) if (parameter->prm_default_value)
*sourceArgIt = CMP_clone_node(tdbb, csb, parameter->prm_default_value); *sourceArgIt = CMP_clone_node(tdbb, csb, parameter->prm_default_value);

View File

@ -804,7 +804,12 @@ ValueListNode* PAR_args(thread_db* tdbb, CompilerScratch* csb, USHORT count, USH
{ {
do do
{ {
*ptr++ = PAR_parse_value(tdbb, csb); if (csb->csb_blr_reader.peekByte() == blr_default_arg)
csb->csb_blr_reader.getByte();
else
*ptr = PAR_parse_value(tdbb, csb);
++ptr;
} while (--count); } while (--count);
} }