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

Allow mixed (positional, named) arguments.

This commit is contained in:
Adriano dos Santos Fernandes 2023-05-02 21:58:44 -03:00
parent e452238cec
commit 5dbd5a46ef
7 changed files with 244 additions and 274 deletions

View File

@ -1,12 +1,15 @@
# Named arguments for function and procedure calling (FB 6.0)
Named arguments allows you to specify function and procedure arguments by their names, rather than only by their positions.
Named arguments allows you to specify function and procedure arguments by their names, rather than only
by their positions.
It is especially useful when the routine have a lot of parameters and you want to specify them in arbitrary order or not specify some of them who have default values.
It is especially useful when the routine have a lot of parameters and you want to specify them in arbitrary
order or not specify some of those who have default values.
As the positional syntax, all arguments without default values are required to be present in the call.
It's currently not possible to mix positional and named arguments in the same call.
A call can use positional, named or mixed arguments. In mixed syntax, positional arguments must appear before
named arguments.
## Syntax
@ -23,8 +26,11 @@ It's currently not possible to mix positional and named arguments in the same ca
[RETURNING_VALUES ...]
<arguments> ::=
<named arguments>
<positional arguments>
<positional arguments> |
[ {<positional arguments>,} ] <named arguments>
<positional arguments> ::=
<value> [ {, <value>}... ]
<named arguments> ::=
<named argument> [ {, <named argument>}... ]
@ -40,6 +46,11 @@ select function_name(parameter2 => 'Two', parameter1 => 1)
from rdb$database
```
```
select function_name(1, parameter2 => 'Two')
from rdb$database
```
```
execute procedure insert_customer(
last_name => 'SCHUMACHER',

View File

@ -12976,7 +12976,7 @@ DmlNode* UdfCallNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
predateCheck(node->function, "blr_invoke_function_type", "blr_invoke_function_args");
argCount = blrReader.getWord();
node->args = PAR_args(tdbb, csb, argCount, (argNames ? argCount : MAX(argCount, node->function->fun_inputs)));
node->args = PAR_args(tdbb, csb, argCount, MAX(argCount, node->function->fun_inputs));
break;
default:
@ -13013,6 +13013,14 @@ DmlNode* UdfCallNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
node->args = PAR_args(tdbb, csb, argCount, node->function->fun_inputs);
}
if (argNames && argNames->getCount() > argCount)
{
blrReader.setPos(argNamesPos);
PAR_error(csb,
Arg::Gds(isc_random) <<
"blr_invoke_function_arg_names count cannot be greater than blr_invoke_function_args");
}
if (!node->function)
{
blrReader.setPos(startPos);
@ -13038,91 +13046,71 @@ DmlNode* UdfCallNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
node->isSubRoutine = node->function->isSubRoutine();
Arg::StatusVector mismatchStatus;
mismatchStatus << Arg::Gds(isc_fun_param_mismatch) << name.toString();
const auto mismatchInitialLength = mismatchStatus.length();
if (!node->args)
node->args = FB_NEW_POOL(pool) ValueListNode(pool);
if (argNames && argNames->getCount() != node->args->items.getCount())
const auto positionalArgCount = argNames ? argCount - argNames->getCount() : argCount;
auto argIt = node->args->items.begin();
LeftPooledMap<MetaName, NestConst<ValueExprNode>> argsByName;
if (positionalArgCount)
{
blrReader.setPos(argNamesPos);
PAR_error(csb,
Arg::Gds(isc_random) << "blr_invoke_function_arg_names count differs from blr_invoke_function_args");
if (argCount > node->function->fun_inputs)
mismatchStatus << Arg::Gds(isc_wronumarg);
for (auto pos = 0; pos < positionalArgCount; ++pos)
{
if (pos < node->function->fun_inputs)
{
const auto& parameter = node->function->getInputFields()[pos];
if (argsByName.put(parameter->prm_name, *argIt))
mismatchStatus << Arg::Gds(isc_param_multiple_assignments) << parameter->prm_name;
}
++argIt;
}
}
if (argNames)
{
LeftPooledMap<MetaName, NestConst<ValueExprNode>> argsByName;
auto argIt = node->args->items.begin();
for (const auto& argName : *argNames)
{
if (argsByName.put(argName, *argIt++))
mismatchStatus << Arg::Gds(isc_param_multiple_assignments) << argName;
}
node->args->items.resize(node->function->getInputFields().getCount());
argIt = node->args->items.begin();
for (auto& parameter : node->function->getInputFields())
{
if (const auto argValue = argsByName.get(parameter->prm_name))
{
*argIt = *argValue;
argsByName.remove(parameter->prm_name);
}
else
{
if (parameter->prm_default_value)
*argIt = CMP_clone_node(tdbb, csb, parameter->prm_default_value);
else
mismatchStatus << Arg::Gds(isc_param_no_default_not_specified) << parameter->prm_name;
}
++argIt;
}
if (argsByName.hasData())
{
for (const auto& argPair : argsByName)
mismatchStatus << Arg::Gds(isc_param_not_exist) << argPair.first;
}
}
else
node->args->items.resize(node->function->getInputFields().getCount());
argIt = node->args->items.begin();
for (auto& parameter : node->function->getInputFields())
{
// Check to see if the argument count matches.
if (argCount > node->function->fun_inputs)
mismatchStatus << Arg::Gds(isc_wronumarg);
else if (argCount < node->function->fun_inputs - node->function->getDefaultCount())
if (const auto argValue = argsByName.get(parameter->prm_name))
{
unsigned pos = 0;
for (auto& parameter : node->function->getInputFields())
{
if (++pos <= argCount)
continue;
mismatchStatus << Arg::Gds(isc_param_no_default_not_specified) << parameter->prm_name;
if (pos >= node->function->fun_inputs - node->function->getDefaultCount())
break;
}
*argIt = *argValue;
argsByName.remove(parameter->prm_name);
}
else
{
for (unsigned pos = argCount; pos < node->function->getInputFields().getCount(); ++pos)
{
auto parameter = node->function->getInputFields()[pos];
fb_assert(parameter->prm_default_value);
node->args->items[pos] = CMP_clone_node(tdbb, csb, parameter->prm_default_value);
}
if (parameter->prm_default_value)
*argIt = CMP_clone_node(tdbb, csb, parameter->prm_default_value);
else
mismatchStatus << Arg::Gds(isc_param_no_default_not_specified) << parameter->prm_name;
}
++argIt;
}
if (mismatchStatus.length() > mismatchInitialLength)
status_exception::raise(mismatchStatus);
if (argsByName.hasData())
{
for (const auto& argPair : argsByName)
mismatchStatus << Arg::Gds(isc_param_not_exist) << argPair.first;
}
if (mismatchStatus.hasData())
status_exception::raise(Arg::Gds(isc_fun_param_mismatch) << name.toString() << mismatchStatus);
// CVC: I will track ufds only if a function is not being dropped.
if (!node->function->isSubRoutine() && csb->collectingDependencies())
@ -13589,20 +13577,31 @@ ValueExprNode* UdfCallNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
Arg::Gds(isc_random) << Arg::Str(name.toString()));
}
auto argIt = node->args->items.begin();
unsigned pos = 0;
while (pos < node->args->items.getCount() - (node->dsqlArgNames ? node->dsqlArgNames->getCount() : 0))
{
if (pos < node->dsqlFunction->udf_arguments.getCount())
{
PASS1_set_parameter_type(dsqlScratch, *argIt++,
[&] (dsc* desc) { *desc = node->dsqlFunction->udf_arguments[pos].desc; },
false);
}
++pos;
}
if (node->dsqlArgNames)
{
fb_assert(node->dsqlArgNames->getCount() == node->args->items.getCount());
fb_assert(node->dsqlArgNames->getCount() <= node->args->items.getCount());
LeftPooledMap<MetaName, const dsc*> argsByName;
for (const auto& arg : node->dsqlFunction->udf_arguments)
argsByName.put(arg.name, &arg.desc);
bool mismatchError = false;
Arg::StatusVector mismatchStatus;
mismatchStatus << Arg::Gds(isc_fun_param_mismatch) << Arg::Str(name.toString());
auto argIt = node->args->items.begin();
for (const auto& argName : *node->dsqlArgNames)
{
@ -13613,32 +13612,13 @@ ValueExprNode* UdfCallNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
false);
}
else
{
mismatchError = true;
mismatchStatus << Arg::Gds(isc_param_not_exist) << argName;
}
++argIt;
}
if (mismatchError)
status_exception::raise(mismatchStatus);
}
else
{
unsigned pos = 0;
for (auto& arg : node->args->items)
{
if (pos < node->dsqlFunction->udf_arguments.getCount())
{
PASS1_set_parameter_type(dsqlScratch, arg,
[&] (dsc* desc) { *desc = node->dsqlFunction->udf_arguments[pos].desc; },
false);
}
++pos;
}
if (mismatchStatus.hasData())
status_exception::raise(Arg::Gds(isc_fun_param_mismatch) << name.toString() << mismatchStatus);
}
return node;

View File

@ -3003,7 +3003,7 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
predateCheck(node->procedure, "blr_invsel_procedure_type", "blr_invsel_procedure_in_args");
inArgCount = blrReader.getWord();
node->inputSources = PAR_args(tdbb, csb, inArgCount,
(inArgNames ? inArgCount : MAX(inArgCount, node->procedure->getInputFields().getCount())));
MAX(inArgCount, node->procedure->getInputFields().getCount()));
break;
case blr_invsel_procedure_out_arg_names:
@ -3071,6 +3071,14 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
break;
}
if (inArgNames && inArgNames->getCount() > node->inputSources->items.getCount())
{
blrReader.setPos(inArgNamesPos);
PAR_error(csb,
Arg::Gds(isc_random) <<
"blr_invsel_procedure_in_arg_names count cannot be greater than blr_invsel_procedure_in_args");
}
if (!node->procedure)
{
blrReader.setPos(blrStartPos);
@ -3092,14 +3100,6 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
if (!node->outputTargets)
node->outputTargets = FB_NEW_POOL(pool) ValueListNode(pool);
if (inArgNames && inArgNames->getCount() != node->inputSources->items.getCount())
{
blrReader.setPos(inArgNamesPos);
PAR_error(csb,
Arg::Gds(isc_random) <<
"blr_invsel_procedure_in_arg_names count differs from blr_invsel_procedure_in_args");
}
if (outArgNames && outArgNames->getCount() != node->outputTargets->items.getCount())
{
blrReader.setPos(outArgNamesPos);
@ -3125,13 +3125,9 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
}
}
Arg::StatusVector mismatchStatus;
mismatchStatus << Arg::Gds(isc_prcmismat) << node->procedure->getName().toString();
const auto mismatchInitialLength = mismatchStatus.length();
node->inputTargets = FB_NEW_POOL(pool) ValueListNode(pool, node->procedure->getInputFields().getCount());
mismatchStatus << CMP_procedure_arguments(
Arg::StatusVector mismatchStatus = CMP_procedure_arguments(
tdbb,
csb,
node->procedure,
@ -3153,8 +3149,8 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
node->outputSources,
node->outputMessage);
if (mismatchStatus.length() > mismatchInitialLength)
status_exception::raise(mismatchStatus);
if (mismatchStatus.hasData())
status_exception::raise(Arg::Gds(isc_prcmismat) << node->procedure->getName().toString() << mismatchStatus);
if (csb->collectingDependencies() && !node->procedure->isSubRoutine())
{
@ -3246,63 +3242,59 @@ ExecProcedureNode* ExecProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
// Handle input parameters.
if (node->dsqlInputArgNames)
if (inputSources && inputSources->items.hasData())
{
fb_assert(node->dsqlInputArgNames->getCount() == node->inputSources->items.getCount());
auto sourceArgIt = node->inputSources->items.begin();
const auto sourceArgEnd = node->inputSources->items.end();
const auto positionalArgCount = node->inputSources->items.getCount() -
(node->dsqlInputArgNames ? node->dsqlInputArgNames->getCount() : 0);
const auto* field = procedure->prc_inputs;
unsigned pos = 0;
LeftPooledMap<MetaName, const dsql_fld*> argsByName;
for (const auto* field = procedure->prc_inputs; field; field = field->fld_next)
argsByName.put(field->fld_name, field);
bool mismatchError = false;
Arg::StatusVector mismatchStatus;
mismatchStatus << Arg::Gds(isc_prcmismat) << dsqlName.toString();
auto argIt = node->inputSources->items.begin();
for (const auto& argName : *node->dsqlInputArgNames)
while (pos < positionalArgCount && field && sourceArgIt != sourceArgEnd)
{
if (const auto field = argsByName.get(argName))
{
dsc descNode;
DsqlDescMaker::fromField(&descNode, *field);
dsc descNode;
DsqlDescMaker::fromField(&descNode, field);
PASS1_set_parameter_type(dsqlScratch, *argIt,
[&] (dsc* desc) { *desc = descNode; },
false);
}
else
{
mismatchError = true;
mismatchStatus << Arg::Gds(isc_param_not_exist) << argName;
}
PASS1_set_parameter_type(dsqlScratch, *sourceArgIt,
[&] (dsc* desc) { *desc = descNode; },
false);
++argIt;
field = field->fld_next;
++pos;
++sourceArgIt;
}
if (mismatchError)
status_exception::raise(mismatchStatus);
}
else
{
if (inputSources && inputSources->items.hasData())
if (node->dsqlInputArgNames)
{
// Initialize this stack variable, and make it look like a node.
dsc descNode;
fb_assert(node->dsqlInputArgNames->getCount() <= node->inputSources->items.getCount());
auto ptr = node->inputSources->items.begin();
const auto end = node->inputSources->items.end();
LeftPooledMap<MetaName, const dsql_fld*> argsByName;
for (const dsql_fld* field = procedure->prc_inputs; field && ptr != end; ++ptr, field = field->fld_next)
for (const auto* field = procedure->prc_inputs; field; field = field->fld_next)
argsByName.put(field->fld_name, field);
Arg::StatusVector mismatchStatus;
for (const auto& argName : *node->dsqlInputArgNames)
{
DEV_BLKCHK(field, dsql_type_fld);
DEV_BLKCHK(*ptr, dsql_type_nod);
DsqlDescMaker::fromField(&descNode, field);
PASS1_set_parameter_type(dsqlScratch, *ptr,
[&] (dsc* desc) { *desc = descNode; },
false);
if (const auto field = argsByName.get(argName))
{
dsc descNode;
DsqlDescMaker::fromField(&descNode, *field);
PASS1_set_parameter_type(dsqlScratch, *sourceArgIt,
[&] (dsc* desc) { *desc = descNode; },
false);
}
else
mismatchStatus << Arg::Gds(isc_param_not_exist) << argName;
++sourceArgIt;
}
if (mismatchStatus.hasData())
status_exception::raise(Arg::Gds(isc_prcmismat) << dsqlName.toString() << mismatchStatus);
}
}

View File

@ -8618,12 +8618,21 @@ argument_list_opt
%type <namedArguments> argument_list
argument_list
: named_argument_list
{ $$ = $1; }
| value_list
{
$$ = newNode<NonPooledPair<ObjectsArray<MetaName>*, ValueListNode*>>();
$$->second = $1;
}
| value_list ',' named_argument_list
{
$$ = $3;
for (auto item : $$->second->items)
$1->add(item);
delete $$->second;
$$->second = $1;
}
;
%type <namedArguments> named_argument_list

View File

@ -544,21 +544,38 @@ dsql_ctx* PASS1_make_context(DsqlCompilerScratch* dsqlScratch, RecordSourceNode*
if (count)
{
auto inputList = context->ctx_proc_inputs;
auto argIt = inputList->items.begin();
const auto argEnd = inputList->items.end();
const auto positionalArgCount = inputList->items.getCount() -
(procNode->dsqlInputArgNames ? procNode->dsqlInputArgNames->getCount() : 0);
const auto* field = procedure->prc_inputs;
unsigned pos = 0;
while (pos < positionalArgCount && field && argIt != argEnd)
{
dsc descNode;
DsqlDescMaker::fromField(&descNode, field);
PASS1_set_parameter_type(dsqlScratch, *argIt,
[&] (dsc* desc) { *desc = descNode; },
false);
field = field->fld_next;
++pos;
++argIt;
}
if (procNode->dsqlInputArgNames)
{
fb_assert(procNode->dsqlInputArgNames->getCount() == inputList->items.getCount());
fb_assert(procNode->dsqlInputArgNames->getCount() <= inputList->items.getCount());
LeftPooledMap<MetaName, const dsql_fld*> argsByName;
for (const auto* field = procedure->prc_inputs; field; field = field->fld_next)
argsByName.put(field->fld_name, field);
bool mismatchError = false;
Arg::StatusVector mismatchStatus;
mismatchStatus << Arg::Gds(isc_prcmismat) << procNode->dsqlName.toString();
auto argIt = inputList->items.begin();
for (const auto& argName : *procNode->dsqlInputArgNames)
{
@ -572,34 +589,13 @@ dsql_ctx* PASS1_make_context(DsqlCompilerScratch* dsqlScratch, RecordSourceNode*
false);
}
else
{
mismatchError = true;
mismatchStatus << Arg::Gds(isc_param_not_exist) << argName;
}
++argIt;
}
if (mismatchError)
status_exception::raise(mismatchStatus);
}
else
{
// Initialize this stack variable, and make it look like a node
dsc descNode;
auto ptr = inputList->items.begin();
const auto end = inputList->items.end();
for (const dsql_fld* field = procedure->prc_inputs; ptr != end; ++ptr, field = field->fld_next)
{
DEV_BLKCHK(field, dsql_type_fld);
DEV_BLKCHK(*ptr, dsql_type_nod);
DsqlDescMaker::fromField(&descNode, field);
PASS1_set_parameter_type(dsqlScratch, *ptr,
[&] (dsc* desc) { *desc = descNode; },
false);
}
if (mismatchStatus.hasData())
status_exception::raise(Arg::Gds(isc_prcmismat) << procNode->dsqlName.toString() << mismatchStatus);
}
}
}

View File

@ -987,7 +987,7 @@ ProcedureSourceNode* ProcedureSourceNode::parse(thread_db* tdbb, CompilerScratch
inArgCount = blrReader.getWord();
node->inputSources = PAR_args(tdbb, csb, inArgCount,
(inArgNames ? inArgCount : MAX(inArgCount, node->procedure->getInputFields().getCount())));
MAX(inArgCount, node->procedure->getInputFields().getCount()));
break;
case blr_invsel_procedure_context:
@ -1069,6 +1069,14 @@ ProcedureSourceNode* ProcedureSourceNode::parse(thread_db* tdbb, CompilerScratch
fb_assert(false);
}
if (inArgNames && inArgNames->getCount() > node->inputSources->items.getCount())
{
blrReader.setPos(inArgNamesPos);
PAR_error(csb,
Arg::Gds(isc_random) <<
"blr_invsel_procedure_in_arg_names count cannot be greater than blr_invsel_procedure_in_args");
}
if (!node->procedure)
{
blrReader.setPos(blrStartPos);
@ -1119,21 +1127,9 @@ ProcedureSourceNode* ProcedureSourceNode::parse(thread_db* tdbb, CompilerScratch
if (!node->inputSources)
node->inputSources = FB_NEW_POOL(pool) ValueListNode(pool);
if (inArgNames && inArgNames->getCount() != node->inputSources->items.getCount())
{
blrReader.setPos(inArgNamesPos);
PAR_error(csb,
Arg::Gds(isc_random) <<
"blr_invsel_procedure_in_arg_names count differs from blr_invsel_procedure_in_args");
}
Arg::StatusVector mismatchStatus;
mismatchStatus << Arg::Gds(isc_prcmismat) << node->procedure->getName().toString();
const auto mismatchInitialLength = mismatchStatus.length();
node->inputTargets = FB_NEW_POOL(pool) ValueListNode(pool, node->procedure->getInputFields().getCount());
mismatchStatus << CMP_procedure_arguments(
Arg::StatusVector mismatchStatus= CMP_procedure_arguments(
tdbb,
csb,
node->procedure,
@ -1144,8 +1140,8 @@ ProcedureSourceNode* ProcedureSourceNode::parse(thread_db* tdbb, CompilerScratch
node->inputTargets,
node->inputMessage);
if (mismatchStatus.length() > mismatchInitialLength)
status_exception::raise(mismatchStatus);
if (mismatchStatus.hasData())
status_exception::raise(Arg::Gds(isc_prcmismat) << node->procedure->getName().toString() << mismatchStatus);
if (csb->collectingDependencies() && !node->procedure->isSubRoutine())
{

View File

@ -484,9 +484,6 @@ Arg::StatusVector CMP_procedure_arguments(
else
targets = FB_NEW_POOL(pool) ValueListNode(pool, argCount);
auto sourceArgIt = sources->items.begin();
auto targetArgIt = targets->items.begin();
// We have a few parameters. Get on with creating the message block
// Outer messages map may start with 2, but they are always in the routine start.
USHORT n = ++csb->csb_msg_number;
@ -519,88 +516,77 @@ Arg::StatusVector CMP_procedure_arguments(
message->format = fmtCopy;
// --- end of fix ---
const auto positionalArgCount = argNames ? argCount - argNames->getCount() : argCount;
auto sourceArgIt = sources->items.begin();
LeftPooledMap<MetaName, NestConst<ValueExprNode>> argsByName;
if (positionalArgCount)
{
if (argCount > fields.getCount())
mismatchStatus << Arg::Gds(isc_wronumarg);
for (auto pos = 0; pos < positionalArgCount; ++pos)
{
if (pos < fields.getCount())
{
const auto& parameter = fields[pos];
if (argsByName.put(parameter->prm_name, *sourceArgIt))
mismatchStatus << Arg::Gds(isc_param_multiple_assignments) << parameter->prm_name;
}
++sourceArgIt;
}
}
if (argNames)
{
LeftPooledMap<MetaName, NestConst<ValueExprNode>> argsByName;
for (const auto& argName : *argNames)
{
if (argsByName.put(argName, *sourceArgIt++))
mismatchStatus << Arg::Gds(isc_param_multiple_assignments) << argName;
}
sourceArgIt = sources->items.begin();
for (auto& parameter : fields)
{
if (const auto argValue = argsByName.get(parameter->prm_name))
{
*sourceArgIt = *argValue;
argsByName.remove(parameter->prm_name);
}
else if (isInput)
{
if (parameter->prm_default_value)
*sourceArgIt = CMP_clone_node(tdbb, csb, parameter->prm_default_value);
else
mismatchStatus << Arg::Gds(isc_param_no_default_not_specified) << parameter->prm_name;
}
++sourceArgIt;
const auto paramNode = FB_NEW_POOL(csb->csb_pool) ParameterNode(csb->csb_pool);
paramNode->messageNumber = message->messageNumber;
paramNode->message = message;
paramNode->argNumber = parameter->prm_number * 2;
const auto paramFlagNode = FB_NEW_POOL(csb->csb_pool) ParameterNode(csb->csb_pool);
paramFlagNode->messageNumber = message->messageNumber;
paramFlagNode->message = message;
paramFlagNode->argNumber = parameter->prm_number * 2 + 1;
paramNode->argFlag = paramFlagNode;
*targetArgIt++ = paramNode;
}
if (argsByName.hasData())
{
for (const auto& argPair : argsByName)
mismatchStatus << Arg::Gds(isc_param_not_exist) << argPair.first;
}
}
else
sourceArgIt = sources->items.begin();
auto targetArgIt = targets->items.begin();
for (auto& parameter : fields)
{
for (unsigned i = 0; i < (isInput ? fields.getCount() : argCount); ++i)
if (const auto argValue = argsByName.get(parameter->prm_name))
{
if (isInput)
{
// default value for parameter
if (i >= argCount)
{
auto parameter = fields[i];
if (parameter->prm_default_value)
*sourceArgIt = CMP_clone_node(tdbb, csb, parameter->prm_default_value);
}
++sourceArgIt;
}
const auto paramNode = FB_NEW_POOL(csb->csb_pool) ParameterNode(csb->csb_pool);
paramNode->messageNumber = message->messageNumber;
paramNode->message = message;
paramNode->argNumber = i * 2;
const auto paramFlagNode = FB_NEW_POOL(csb->csb_pool) ParameterNode(csb->csb_pool);
paramFlagNode->messageNumber = message->messageNumber;
paramFlagNode->message = message;
paramFlagNode->argNumber = i * 2 + 1;
paramNode->argFlag = paramFlagNode;
*targetArgIt++ = paramNode;
*sourceArgIt = *argValue;
argsByName.remove(parameter->prm_name);
}
else if (isInput)
{
if (parameter->prm_default_value)
*sourceArgIt = CMP_clone_node(tdbb, csb, parameter->prm_default_value);
else
mismatchStatus << Arg::Gds(isc_param_no_default_not_specified) << parameter->prm_name;
}
++sourceArgIt;
const auto paramNode = FB_NEW_POOL(csb->csb_pool) ParameterNode(csb->csb_pool);
paramNode->messageNumber = message->messageNumber;
paramNode->message = message;
paramNode->argNumber = parameter->prm_number * 2;
const auto paramFlagNode = FB_NEW_POOL(csb->csb_pool) ParameterNode(csb->csb_pool);
paramFlagNode->messageNumber = message->messageNumber;
paramFlagNode->message = message;
paramFlagNode->argNumber = parameter->prm_number * 2 + 1;
paramNode->argFlag = paramFlagNode;
*targetArgIt++ = paramNode;
}
if (argsByName.hasData())
{
for (const auto& argPair : argsByName)
mismatchStatus << Arg::Gds(isc_param_not_exist) << argPair.first;
}
}