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

Reduce usage of legacy (and unsafe) nodes related to PSQL parameters and variables.

Use btyacc feature "inherited attributes" (kind of parameters for non-terminals).
This commit is contained in:
asfernandes 2009-11-21 20:42:27 +00:00
parent 79f29a9b41
commit 200a63b1b4
11 changed files with 234 additions and 306 deletions

View File

@ -298,16 +298,17 @@ void DdlNode::resetContextStack()
//----------------------
TypeClause::TypeClause(dsql_fld* aLegacyField, dsql_str* aLegacyCollate)
TypeClause::TypeClause(dsql_fld* aLegacyField, const MetaName& aCollate)
: legacyField(aLegacyField),
legacyCollate(aLegacyCollate)
collate(aCollate)
{
}
void TypeClause::resolve(CompiledStatement* compiledStatement)
{
DDL_resolve_intl_type(compiledStatement, legacyField, legacyCollate);
DDL_resolve_intl_type(compiledStatement, legacyField,
(collate.isEmpty() ? NULL : MAKE_cstring(collate.c_str())));
type = legacyField->fld_dtype;
length = legacyField->fld_length;
@ -318,7 +319,7 @@ void TypeClause::resolve(CompiledStatement* compiledStatement)
charLength = legacyField->fld_character_length;
charSetId = legacyField->fld_character_set_id;
collationId = legacyField->fld_collation_id;
collateSpecified = legacyCollate != NULL;
collateSpecified = collate.hasData();
textType = legacyField->fld_ttype;
fullDomain = legacyField->fld_full_domain;
notNull = legacyField->fld_not_nullable;
@ -341,8 +342,8 @@ void TypeClause::print(string& text) const
//----------------------
ParameterClause::ParameterClause(dsql_fld* field, dsql_str* collate, dsql_nod* dflt)
: TypeClause(field, collate),
ParameterClause::ParameterClause(dsql_fld* field, const MetaName& aCollate, dsql_nod* dflt)
: TypeClause(field, aCollate),
name(field->fld_name),
legacyDefault(dflt)
{
@ -357,28 +358,6 @@ void ParameterClause::print(string& text) const
}
void ParameterClause::fromLegacyParameterList(Array<ParameterClause>& parameters, dsql_nod* list)
{
if (list)
{
fb_assert(list->nod_type == Dsql::nod_list);
for (unsigned i = 0; i < list->nod_count; ++i)
{
dsql_nod* defField = list->nod_arg[i];
fb_assert(defField->nod_type == Dsql::nod_def_field);
dsql_fld* field = (dsql_fld*) defField->nod_arg[e_dfl_field];
dsql_str* collate = (dsql_str*) defField->nod_arg[e_dfl_collate];
dsql_nod* dflt = defField->nod_arg[e_dfl_default];
ParameterClause parameter(field, collate, dflt);
parameters.add(parameter);
}
}
}
//----------------------
@ -1092,36 +1071,15 @@ void DropFunctionNode::execute(thread_db* tdbb, jrd_tra* transaction)
void ProcedureNode::genReturn()
{
GEN_return(compiledStatement, getCreateAlterNode()->legacyReturns, false);
GEN_return(compiledStatement, getCreateAlterNode()->outputVariables, false);
}
dsql_nod* ProcedureNode::resolveVariable(const dsql_str* varName)
{
// try to resolve variable name against input and output parameters and local variables
CreateAlterProcedureNode* node = getCreateAlterNode();
dsql_nod* varNode;
if (node->legacyParameters)
{
if (varNode = PASS1_resolve_variable_name(node->legacyParameters, varName))
return varNode;
}
if (node->legacyReturns)
{
if (varNode = PASS1_resolve_variable_name(node->legacyReturns, varName))
return varNode;
}
if (node->localDeclList)
{
if (varNode = PASS1_resolve_variable_name(node->localDeclList, varName))
return varNode;
}
return NULL;
return PASS1_resolve_variable_name(node->variables, varName);
}
@ -1177,6 +1135,20 @@ Node* CreateAlterProcedureNode::internalDsqlPass()
{
// insure that variable names do not duplicate parameter names
SortedArray<MetaName> names;
for (size_t i = 0; i < parameters.getCount(); ++i)
{
ParameterClause& parameter = parameters[i];
names.add(parameter.name);
}
for (size_t i = 0; i < returns.getCount(); ++i)
{
ParameterClause& parameter = returns[i];
names.add(parameter.name);
}
const dsql_nod* const* ptr = variables->nod_arg;
for (const dsql_nod* const* const end = ptr + variables->nod_count; ptr < end; ptr++)
{
@ -1185,46 +1157,13 @@ Node* CreateAlterProcedureNode::internalDsqlPass()
const dsql_fld* field = (dsql_fld*) (*ptr)->nod_arg[e_dfl_field];
DEV_BLKCHK(field, dsql_type_fld);
const dsql_nod* parameters = legacyParameters;
if (parameters)
if (names.exist(field->fld_name))
{
const dsql_nod* const* ptr2 = parameters->nod_arg;
for (const dsql_nod* const* const end2 =
ptr2 + parameters->nod_count; ptr2 < end2; ptr2++)
{
const dsql_fld* field2 = (dsql_fld*) (*ptr2)->nod_arg[e_dfl_field];
DEV_BLKCHK(field2, dsql_type_fld);
if (field->fld_name == field2->fld_name)
{
status_exception::raise(
Arg::Gds(isc_sqlerr) <<
Arg::Num(-901) <<
Arg::Gds(isc_dsql_var_conflict) <<
Arg::Str(field->fld_name));
}
}
}
parameters = legacyReturns;
if (parameters)
{
const dsql_nod* const* ptr2 = parameters->nod_arg;
for (const dsql_nod* const* const end2 =
ptr2 + parameters->nod_count; ptr2 < end2; ptr2++)
{
const dsql_fld* field2 = (dsql_fld*) (*ptr2)->nod_arg[e_dfl_field];
DEV_BLKCHK(field2, dsql_type_fld);
if (field->fld_name == field2->fld_name)
{
status_exception::raise(
Arg::Gds(isc_sqlerr) <<
Arg::Num(-901) <<
Arg::Gds(isc_dsql_var_conflict) <<
Arg::Str(field->fld_name));
}
}
status_exception::raise(
Arg::Gds(isc_sqlerr) <<
Arg::Num(-901) <<
Arg::Gds(isc_dsql_var_conflict) <<
Arg::Str(field->fld_name));
}
}
}
@ -1768,8 +1707,8 @@ void CreateAlterProcedureNode::compile(thread_db* tdbb, jrd_tra* /*transaction*/
compiledStatement->append_uchar(blr_short);
compiledStatement->append_uchar(0);
legacyParameters->nod_arg[i] = MAKE_variable(parameter.legacyField,
parameter.name.c_str(), VAR_input, 0, (USHORT) (2 * i), 0);
variables.add(MAKE_variable(parameter.legacyField,
parameter.name.c_str(), VAR_input, 0, (USHORT) (2 * i), 0));
}
}
@ -1791,8 +1730,11 @@ void CreateAlterProcedureNode::compile(thread_db* tdbb, jrd_tra* /*transaction*/
compiledStatement->append_uchar(blr_short);
compiledStatement->append_uchar(0);
legacyReturns->nod_arg[i] = MAKE_variable(parameter.legacyField,
dsql_nod* var = MAKE_variable(parameter.legacyField,
parameter.name.c_str(), VAR_output, 1, (USHORT) (2 * i), i);
variables.add(var);
outputVariables.add(var);
}
}
@ -1825,23 +1767,18 @@ void CreateAlterProcedureNode::compile(thread_db* tdbb, jrd_tra* /*transaction*/
}
}
if (returns.getCount() != 0)
for (Array<dsql_nod*>::const_iterator i = outputVariables.begin(); i != outputVariables.end(); ++i)
{
dsql_nod* params = legacyReturns;
dsql_nod** ptr = params->nod_arg;
for (const dsql_nod* const* const end = ptr + params->nod_count; ptr < end; ptr++)
{
dsql_nod* parameter = *ptr;
dsql_var* variable = (dsql_var*) parameter->nod_arg[Dsql::e_var_variable];
DDL_put_local_variable(compiledStatement, variable, 0, NULL);
}
dsql_nod* parameter = *i;
dsql_var* variable = (dsql_var*) parameter->nod_arg[Dsql::e_var_variable];
DDL_put_local_variable(compiledStatement, variable, 0, NULL);
}
// ASF: This is here to not change the old logic (proc_flag)
// of previous calls to PASS1_node and PASS1_statement.
compiledStatement->setPsql(true);
DDL_put_local_variables(compiledStatement, localDeclList, returns.getCount());
DDL_put_local_variables(compiledStatement, localDeclList, returns.getCount(), variables);
compiledStatement->append_uchar(blr_stall);
// put a label before body of procedure,
@ -1855,7 +1792,7 @@ void CreateAlterProcedureNode::compile(thread_db* tdbb, jrd_tra* /*transaction*/
compiledStatement->req_type = REQ_DDL;
compiledStatement->append_uchar(blr_end);
GEN_return(compiledStatement, legacyReturns, true);
GEN_return(compiledStatement, outputVariables, true);
compiledStatement->append_uchar(blr_end);
compiledStatement->append_uchar(blr_eoc);
@ -2052,13 +1989,8 @@ void RecreateProcedureNode::execute(thread_db* tdbb, jrd_tra* transaction)
dsql_nod* TriggerNode::resolveVariable(const dsql_str* varName)
{
// try to resolve variable name against local variables
CreateAlterTriggerNode* node = getCreateAlterNode();
if (node->localDeclList)
return PASS1_resolve_variable_name(node->localDeclList, varName);
return NULL;
return PASS1_resolve_variable_name(node->variables, varName);
}
@ -2404,7 +2336,7 @@ void CreateAlterTriggerNode::compile(thread_db* tdbb, jrd_tra* /*transaction*/)
compiledStatement->setPsql(true);
DDL_put_local_variables(compiledStatement, localDeclList, 0);
DDL_put_local_variables(compiledStatement, localDeclList, 0, variables);
compiledStatement->req_scope_level++;
// dimitr: I see no reason to deny EXIT command in triggers,

View File

@ -49,7 +49,7 @@ public:
class TypeClause
{
public:
explicit TypeClause(dsql_fld* aField, dsql_str* aCollate);
explicit TypeClause(dsql_fld* aField, const Firebird::MetaName& aCollate);
virtual ~TypeClause() {}
public:
@ -78,21 +78,18 @@ public:
public:
dsql_fld* legacyField;
dsql_str* legacyCollate;
Firebird::MetaName collate;
};
class ParameterClause : public TypeClause
{
public:
explicit ParameterClause(dsql_fld* field, dsql_str* collate, dsql_nod* dflt);
explicit ParameterClause(dsql_fld* field, const Firebird::MetaName& aCollate, dsql_nod* dflt);
public:
void print(Firebird::string& text) const;
public:
static void fromLegacyParameterList(Firebird::Array<ParameterClause>& parameters, dsql_nod* list);
public:
Firebird::MetaName name;
dsql_nod* legacyDefault;
@ -150,10 +147,10 @@ class CreateAlterFunctionNode : public DdlNode
{
public:
explicit CreateAlterFunctionNode(MemoryPool& pool, const Firebird::string& sqlText,
const Firebird::MetaName& aName, const TypeClause& aReturnType)
const Firebird::MetaName& aName)
: DdlNode(pool, sqlText),
name(pool, aName),
returnType(aReturnType),
returnType(NULL, NULL),
create(true),
alter(false),
external(NULL),
@ -243,8 +240,8 @@ public:
external(NULL),
parameters(pool),
returns(pool),
legacyParameters(NULL),
legacyReturns(NULL),
variables(pool),
outputVariables(pool),
source(pool),
localDeclList(NULL),
body(NULL),
@ -283,8 +280,8 @@ public:
ExternalClause* external;
Firebird::Array<ParameterClause> parameters;
Firebird::Array<ParameterClause> returns;
dsql_nod* legacyParameters;
dsql_nod* legacyReturns;
Firebird::Array<dsql_nod*> variables;
Firebird::Array<dsql_nod*> outputVariables;
Firebird::string source;
dsql_nod* localDeclList;
dsql_nod* body;
@ -393,6 +390,7 @@ public:
relationName(p),
external(NULL),
source(p),
variables(p),
localDeclList(NULL),
body(NULL),
compiled(false),
@ -445,6 +443,7 @@ public:
TriStateType<int> position;
ExternalClause* external;
Firebird::string source;
Firebird::Array<dsql_nod*> variables;
dsql_nod* localDeclList;
dsql_nod* body;
bool compiled;

View File

@ -378,7 +378,7 @@ ExecBlockNode* ExecBlockNode::internalDsqlPass()
{
compiledStatement->blockNode = this;
if (legacyReturns && legacyReturns->nod_count)
if (returns.hasData())
compiledStatement->req_type = REQ_SELECT_BLOCK;
else
compiledStatement->req_type = REQ_EXEC_BLOCK;
@ -389,13 +389,12 @@ ExecBlockNode* ExecBlockNode::internalDsqlPass()
node->compiledStatement = compiledStatement;
node->legacyParameters = PASS1_node_psql(compiledStatement, legacyParameters, false);
node->legacyReturns = legacyReturns;
node->returns = returns;
node->localDeclList = localDeclList;
node->body = body;
const size_t count = node->legacyParameters ? node->legacyParameters->nod_count : 0 +
node->legacyReturns ? node->legacyReturns->nod_count : 0 +
node->returns.getCount() +
node->localDeclList ? node->localDeclList->nod_count : 0;
if (count)
@ -403,7 +402,22 @@ ExecBlockNode* ExecBlockNode::internalDsqlPass()
StrArray names(*getDefaultMemoryPool(), count);
PASS1_check_unique_fields_names(names, node->legacyParameters);
PASS1_check_unique_fields_names(names, node->legacyReturns);
// Hand-made PASS1_check_unique_fields_names for array of ParameterClause
for (size_t i = 0; i < returns.getCount(); ++i)
{
ParameterClause& parameter = returns[i];
size_t pos;
if (!names.find(parameter.name.c_str(), pos))
names.insert(pos, parameter.name.c_str());
else
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-637) <<
Arg::Gds(isc_dsql_duplicate_spec) << Arg::Str(parameter.name));
}
}
PASS1_check_unique_fields_names(names, node->localDeclList);
}
@ -413,9 +427,20 @@ ExecBlockNode* ExecBlockNode::internalDsqlPass()
void ExecBlockNode::print(string& text, Array<dsql_nod*>& nodes) const
{
text = "ExecBlockNode";
text = "ExecBlockNode\n";
text += " Returns:\n";
for (size_t i = 0; i < returns.getCount(); ++i)
{
const ParameterClause& parameter = returns[i];
string s;
parameter.print(s);
text += " " + s + "\n";
}
nodes.add(legacyParameters);
nodes.add(legacyReturns);
nodes.add(localDeclList);
nodes.add(body);
}
@ -429,13 +454,11 @@ void ExecBlockNode::genBlr()
compiledStatement->begin_debug();
USHORT inputs = 0, outputs = 0, locals = 0;
dsql_nod* parameters;
// now do the input parameters
if (parameters = legacyParameters)
if (legacyParameters)
{
USHORT position = 0;
dsql_nod* parameters = legacyParameters;
dsql_nod** ptr = parameters->nod_arg;
for (const dsql_nod* const* const end = ptr + parameters->nod_count; ptr < end; ptr++)
{
@ -446,31 +469,29 @@ void ExecBlockNode::genBlr()
DDL_resolve_intl_type(compiledStatement, field,
reinterpret_cast<const dsql_str*>(parameter->nod_arg[Dsql::e_dfl_collate]));
*ptr = MAKE_variable(field, field->fld_name.c_str(), VAR_input, 0,
(USHORT) (2 * position), locals);
variables.add(MAKE_variable(field, field->fld_name.c_str(),
VAR_input, 0, (USHORT) (2 * inputs), locals));
// ASF: do not increment locals here - CORE-2341
position++;
inputs++;
}
inputs = position;
}
unsigned returnsPos = variables.getCount();
// now do the output parameters
if (parameters = legacyReturns)
for (size_t i = 0; i < returns.getCount(); ++i)
{
USHORT position = 0;
dsql_nod** ptr = parameters->nod_arg;
for (const dsql_nod* const* const end = ptr + parameters->nod_count; ptr < end; ++ptr)
{
dsql_fld* field = (dsql_fld*) (*ptr)->nod_arg[Dsql::e_dfl_field];
ParameterClause& parameter = returns[i];
DDL_resolve_intl_type(compiledStatement, field,
reinterpret_cast<const dsql_str*>((*ptr)->nod_arg[Dsql::e_dfl_collate]));
parameter.resolve(compiledStatement);
*ptr = MAKE_variable(field, field->fld_name.c_str(), VAR_output, 1,
(USHORT) (2 * position), locals++);
position++;
}
outputs = position;
dsql_nod* var = MAKE_variable(parameter.legacyField,
parameter.name.c_str(), VAR_output, 1, (USHORT) (2 * outputs), locals++);
variables.add(var);
outputVariables.add(var);
++outputs;
}
compiledStatement->append_uchar(blr_begin);
@ -484,20 +505,13 @@ void ExecBlockNode::genBlr()
else
compiledStatement->req_send = NULL;
if (outputs)
for (Array<dsql_nod*>::const_iterator i = outputVariables.begin(); i != outputVariables.end(); ++i)
{
USHORT position = 0;
parameters = legacyReturns;
dsql_nod** ptr = parameters->nod_arg;
for (const dsql_nod* const* const end = ptr + parameters->nod_count; ptr < end; ptr++)
{
dsql_par* param =
MAKE_parameter(compiledStatement->req_receive, true, true, ++position, *ptr);
param->par_node = *ptr;
MAKE_desc(compiledStatement, &param->par_desc, *ptr, NULL);
param->par_desc.dsc_flags |= DSC_nullable;
}
dsql_par* param = MAKE_parameter(compiledStatement->req_receive, true, true,
(i - outputVariables.begin()) + 1, *i);
param->par_node = *i;
MAKE_desc(compiledStatement, &param->par_desc, *i, NULL);
param->par_desc.dsc_flags |= DSC_nullable;
}
// Set up parameter to handle EOF
@ -519,47 +533,38 @@ void ExecBlockNode::genBlr()
compiledStatement->append_uchar(blr_begin);
if (parameters = legacyParameters)
for (unsigned i = 0; i < returnsPos; ++i)
{
dsql_nod** ptr = parameters->nod_arg;
for (const dsql_nod* const* const end = ptr + parameters->nod_count; ptr < end; ptr++)
{
const dsql_nod* parameter = *ptr;
const dsql_var* variable = (dsql_var*) parameter->nod_arg[Dsql::e_var_variable];
const dsql_fld* field = variable->var_field;
const dsql_nod* parameter = variables[i];
const dsql_var* variable = (dsql_var*) parameter->nod_arg[Dsql::e_var_variable];
const dsql_fld* field = variable->var_field;
if (field->fld_full_domain || field->fld_not_nullable)
{
// ASF: Validation of execute block input parameters is different than procedure
// parameters, because we can't generate messages using the domains due to the
// connection charset influence. So to validate, we cast them and assign to null.
compiledStatement->append_uchar(blr_assignment);
compiledStatement->append_uchar(blr_cast);
DDL_put_field_dtype(compiledStatement, field, true);
compiledStatement->append_uchar(blr_parameter2);
compiledStatement->append_uchar(0);
compiledStatement->append_ushort(variable->var_msg_item);
compiledStatement->append_ushort(variable->var_msg_item + 1);
compiledStatement->append_uchar(blr_null);
}
if (field->fld_full_domain || field->fld_not_nullable)
{
// ASF: Validation of execute block input parameters is different than procedure
// parameters, because we can't generate messages using the domains due to the
// connection charset influence. So to validate, we cast them and assign to null.
compiledStatement->append_uchar(blr_assignment);
compiledStatement->append_uchar(blr_cast);
DDL_put_field_dtype(compiledStatement, field, true);
compiledStatement->append_uchar(blr_parameter2);
compiledStatement->append_uchar(0);
compiledStatement->append_ushort(variable->var_msg_item);
compiledStatement->append_ushort(variable->var_msg_item + 1);
compiledStatement->append_uchar(blr_null);
}
}
if (outputs)
for (Array<dsql_nod*>::const_iterator i = outputVariables.begin(); i != outputVariables.end(); ++i)
{
parameters = legacyReturns;
dsql_nod** ptr = parameters->nod_arg;
for (const dsql_nod* const* const end = ptr + parameters->nod_count; ptr < end; ptr++)
{
dsql_nod* parameter = *ptr;
dsql_var* variable = (dsql_var*) parameter->nod_arg[Dsql::e_var_variable];
DDL_put_local_variable(compiledStatement, variable, 0, NULL);
}
dsql_nod* parameter = *i;
dsql_var* variable = (dsql_var*) parameter->nod_arg[Dsql::e_var_variable];
DDL_put_local_variable(compiledStatement, variable, 0, NULL);
}
compiledStatement->setPsql(true);
DDL_put_local_variables(compiledStatement, localDeclList, locals);
DDL_put_local_variables(compiledStatement, localDeclList, locals, variables);
compiledStatement->req_loop_level = 0;
@ -578,7 +583,7 @@ void ExecBlockNode::genBlr()
compiledStatement->req_type = REQ_EXEC_BLOCK;
compiledStatement->append_uchar(blr_end);
GEN_return(compiledStatement, legacyReturns, true);
GEN_return(compiledStatement, outputVariables, true);
compiledStatement->append_uchar(blr_end);
compiledStatement->end_debug();
@ -587,35 +592,14 @@ void ExecBlockNode::genBlr()
void ExecBlockNode::genReturn()
{
GEN_return(compiledStatement, legacyReturns, false);
GEN_return(compiledStatement, outputVariables, false);
}
dsql_nod* ExecBlockNode::resolveVariable(const dsql_str* varName)
{
// try to resolve variable name against input and output parameters and local variables
dsql_nod* varNode;
if (localDeclList)
{
if (varNode = PASS1_resolve_variable_name(localDeclList, varName))
return varNode;
}
if (legacyParameters)
{
if (varNode = PASS1_resolve_variable_name(legacyParameters, varName))
return varNode;
}
if (legacyReturns)
{
if (varNode = PASS1_resolve_variable_name(legacyReturns, varName))
return varNode;
}
return NULL;
return PASS1_resolve_variable_name(variables, varName);
}

View File

@ -26,6 +26,7 @@
#include "../jrd/common.h"
#include "../jrd/blr.h"
#include "../dsql/Nodes.h"
#include "../dsql/DdlNodes.h"
#include "../common/classes/MetaName.h"
namespace Jrd {
@ -105,8 +106,10 @@ class ExecBlockNode : public DsqlOnlyStmtNode, public BlockNode
public:
explicit ExecBlockNode(MemoryPool& pool)
: DsqlOnlyStmtNode(pool),
returns(pool),
variables(pool),
outputVariables(pool),
legacyParameters(NULL),
legacyReturns(NULL),
localDeclList(NULL),
body(NULL)
{
@ -127,8 +130,10 @@ private:
static dsql_par* revertParametersOrder(dsql_par* parameter, dsql_par* prev);
public:
Firebird::Array<ParameterClause> returns;
Firebird::Array<dsql_nod*> variables;
Firebird::Array<dsql_nod*> outputVariables;
dsql_nod* legacyParameters;
dsql_nod* legacyReturns;
dsql_nod* localDeclList;
dsql_nod* body;
};

View File

@ -5271,7 +5271,8 @@ void DDL_put_local_variable( CompiledStatement* statement, dsql_var* variable,
}
void DDL_put_local_variables(CompiledStatement* statement, dsql_nod* parameters, SSHORT locals)
void DDL_put_local_variables(CompiledStatement* statement, const dsql_nod* parameters,
SSHORT locals, Array<dsql_nod*>& variables)
{
/**************************************
*
@ -5287,7 +5288,7 @@ void DDL_put_local_variables(CompiledStatement* statement, dsql_nod* parameters,
if (parameters)
{
dsql_nod** ptr = parameters->nod_arg;
dsql_nod* const* ptr = parameters->nod_arg;
for (const dsql_nod* const* const end = ptr + parameters->nod_count; ptr < end; ptr++)
{
dsql_nod* parameter = *ptr;
@ -5312,8 +5313,8 @@ void DDL_put_local_variables(CompiledStatement* statement, dsql_nod* parameters,
}
dsql_nod* var_node = MAKE_variable(field, field->fld_name.c_str(), VAR_local, 0, 0, locals);
variables.add(var_node);
*ptr = var_node;
dsql_var* variable = (dsql_var*) var_node->nod_arg[e_var_variable];
DDL_put_local_variable(statement, variable, parameter,
reinterpret_cast<const dsql_str*>(parameter->nod_arg[e_dfl_collate]));

View File

@ -69,6 +69,7 @@ void DDL_resolve_intl_type(Jrd::CompiledStatement*, Jrd::dsql_fld*, const Jrd::d
void DDL_resolve_intl_type2(Jrd::CompiledStatement*, Jrd::dsql_fld*, const Jrd::dsql_str*, bool);
void DDL_put_local_variable(Jrd::CompiledStatement*, Jrd::dsql_var*, Jrd::dsql_nod*, const Jrd::dsql_str*);
void DDL_put_local_variables(Jrd::CompiledStatement*, Jrd::dsql_nod*, SSHORT);
void DDL_put_local_variables(Jrd::CompiledStatement*, const Jrd::dsql_nod*, SSHORT,
Firebird::Array<Jrd::dsql_nod*>& variables);
#endif // DSQL_DDL_PROTO_H

View File

@ -2308,7 +2308,7 @@ static void gen_relation( CompiledStatement* statement, dsql_ctx* context)
@param eos_flag
**/
void GEN_return( CompiledStatement* statement, const dsql_nod* parameters, bool eos_flag)
void GEN_return(CompiledStatement* statement, const Array<dsql_nod*>& variables, bool eos_flag)
{
if (!eos_flag)
stuff(statement, blr_begin);
@ -2318,23 +2318,20 @@ void GEN_return( CompiledStatement* statement, const dsql_nod* parameters, bool
stuff(statement, blr_begin);
USHORT outputs = 0;
if (parameters)
for (Array<dsql_nod*>::const_iterator i = variables.begin(); i != variables.end(); ++i)
{
const dsql_nod* const* ptr = parameters->nod_arg;
for (const dsql_nod* const* const end = ptr + parameters->nod_count; ptr < end; ptr++)
{
outputs++;
const dsql_nod* parameter = *ptr;
const dsql_var* variable = (dsql_var*) parameter->nod_arg[e_var_variable];
stuff(statement, blr_assignment);
stuff(statement, blr_variable);
stuff_word(statement, variable->var_variable_number);
stuff(statement, blr_parameter2);
stuff(statement, variable->var_msg_number);
stuff_word(statement, variable->var_msg_item);
stuff_word(statement, variable->var_msg_item + 1);
}
outputs++;
const dsql_nod* parameter = *i;
const dsql_var* variable = (dsql_var*) parameter->nod_arg[e_var_variable];
stuff(statement, blr_assignment);
stuff(statement, blr_variable);
stuff_word(statement, variable->var_variable_number);
stuff(statement, blr_parameter2);
stuff(statement, variable->var_msg_number);
stuff_word(statement, variable->var_msg_item);
stuff_word(statement, variable->var_msg_item + 1);
}
stuff(statement, blr_assignment);
stuff(statement, blr_literal);
stuff(statement, blr_short);

View File

@ -29,7 +29,7 @@ void GEN_expr(Jrd::CompiledStatement*, Jrd::dsql_nod*);
void GEN_hidden_variables(Jrd::CompiledStatement* statement, bool inExpression);
void GEN_port(Jrd::CompiledStatement*, Jrd::dsql_msg*);
void GEN_request(Jrd::CompiledStatement*, Jrd::dsql_nod*);
void GEN_return(Jrd::CompiledStatement*, const Jrd::dsql_nod*, bool);
void GEN_return(Jrd::CompiledStatement*, const Firebird::Array<Jrd::dsql_nod*>& variables, bool);
void GEN_start_transaction(Jrd::CompiledStatement*, const Jrd::dsql_nod*);
void GEN_statement(Jrd::CompiledStatement*, Jrd::dsql_nod*);

View File

@ -626,6 +626,7 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
Jrd::dsql_fld* legacyField;
TEXT* textPtr;
Jrd::ExternalClause* externalClause;
Firebird::Array<Jrd::ParameterClause>* parametersClause;
Jrd::StmtNode* stmtNode;
Jrd::DdlNode* ddlNode;
Jrd::CreateAlterFunctionNode* createAlterFunctionNode;
@ -635,6 +636,7 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
Firebird::Array<Jrd::CreateAlterPackageNode::Item>* packageItems;
Jrd::CreateAlterPackageNode::Item packageItem;
Jrd::CreatePackageBodyNode* createPackageBodyNode;
Jrd::ExecBlockNode* execBlockNode;
}
%type <legacyNode> access_mode access_type aggregate_function alias_list
@ -650,7 +652,7 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
%type <legacyNode> begin_string begin_trigger between_predicate bit_length_expression
%type <legacyNode> blob_filter_subtype blob_io blob_segsize blob_subtype blob_subtype_io
%type <legacyNode> blob_subtype_value_io blob_type block_input_params block_parameter
%type <legacyNode> block_parameters breakleave
%type <legacyNode> block_proc_parameter block_parameters breakleave
%type <legacyNode> case_abbreviation case_expression case_operand case_result case_specification
%type <legacyNode> cast_specification char_length_expression character_keyword character_type
@ -705,10 +707,12 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
%type <legacyNode> having_clause
%type <legacyNode> in_predicate in_predicate_value
%type <legacyNode> index_definition index_list init_alter_db input_parameters
%type <legacyNode> input_proc_parameter input_proc_parameters ins_column_list ins_column_parens
%type <legacyNode> index_definition index_list init_alter_db
%type <legacyNode> ins_column_list ins_column_parens
%type <legacyNode> ins_column_parens_opt insert integer_keyword internal_info
%type <legacyNode> iso_mode isolation_mode
%type input_parameters(<parametersClause>) input_proc_parameter(<parametersClause>)
%type input_proc_parameters(<parametersClause>)
%type <legacyNode> join_condition join_specification join_type joined_table
@ -734,12 +738,13 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
%type <legacyNode> octet_length_expression open_cursor opt_snapshot optional_retain
%type <legacyNode> optional_savepoint optional_work order_clause order_direction order_item order_list
%type <legacyNode> output_parameters output_proc_parameters
%type output_parameters(<parametersClause>) output_proc_parameter(<parametersClause>)
%type output_proc_parameters(<parametersClause>)
%type <legacyNode> param_mechanism parameter plan_clause
%type <legacyNode> plan_expression plan_item plan_item_list plan_type
%type <legacyNode> post_event prec_scale predicate primary_constraint privilege
%type <legacyNode> privilege_list privileges proc_block proc_inputs proc_outputs_opt proc_parameter
%type <legacyNode> privilege_list privileges proc_block proc_inputs proc_outputs_opt
%type <legacyNode> proc_privileges proc_statement proc_statements
%type <legacyStr> passwd_clause passwd_opt
%type <int32Val> pos_short_integer precision_opt
@ -807,7 +812,8 @@ inline void check_copy_incr(char*& to, const char ch, const char* const string)
%type <boolVal> release_only_opt
%type <ddlNode> alter_charset_clause
%type <stmtNode> if_then_else in_autonomous_transaction exec_block
%type <stmtNode> if_then_else in_autonomous_transaction
%type <execBlockNode> exec_block
%type <createAlterFunctionNode> alter_function_clause function_clause function_clause_start replace_function_clause
%type <createAlterProcedureNode> alter_procedure_clause procedure_clause procedure_clause_start replace_procedure_clause
@ -1870,14 +1876,13 @@ procedure_clause
;
procedure_clause_start
: symbol_procedure_name input_parameters output_parameters
{
$$ = FB_NEW(getPool()) CreateAlterProcedureNode(getPool(), compilingText, toName($1));
ParameterClause::fromLegacyParameterList($$->parameters, $2);
ParameterClause::fromLegacyParameterList($$->returns, $3);
$$->legacyParameters = $2;
$$->legacyReturns = $3;
}
: symbol_procedure_name
{
$$ = FB_NEW(getPool()) CreateAlterProcedureNode(
getPool(), compilingText, toName($1));
}
input_parameters(&$2->parameters) output_parameters(&$2->returns)
{ $$ = $2; }
;
alter_procedure_clause
@ -1897,40 +1902,36 @@ replace_procedure_clause
}
;
input_parameters : '(' input_proc_parameters ')'
{ $$ = make_list ($2); }
| '(' ')'
{ $$ = NULL; }
|
{ $$ = NULL; }
;
input_parameters($parameters)
:
| '(' ')'
| '(' input_proc_parameters($parameters) ')'
;
output_parameters : RETURNS '(' output_proc_parameters ')'
{ $$ = make_list ($3); }
|
{ $$ = NULL; }
;
output_parameters($parameters)
:
| RETURNS '(' output_proc_parameters($parameters) ')'
;
input_proc_parameters : input_proc_parameter
| input_proc_parameters ',' input_proc_parameter
{ $$ = make_node (nod_list, 2, $1, $3); }
;
input_proc_parameters($parameters)
: input_proc_parameter($parameters)
| input_proc_parameters ',' input_proc_parameter($parameters)
;
input_proc_parameter : simple_column_def_name domain_or_non_array_type collate_clause
default_par_opt
{ $$ = make_node (nod_def_field, (int) e_dfl_count,
$1, $4, NULL, $3, NULL, NULL); }
;
input_proc_parameter($parameters)
: simple_column_def_name domain_or_non_array_type collate_clause default_par_opt
{ $parameters->add(ParameterClause($1, toName($3), $4)); }
;
output_proc_parameters : proc_parameter
| output_proc_parameters ',' proc_parameter
{ $$ = make_node (nod_list, 2, $1, $3); }
;
output_proc_parameters($parameters)
: output_proc_parameter
| output_proc_parameters ',' output_proc_parameter($parameters)
;
proc_parameter : simple_column_def_name domain_or_non_array_type collate_clause
{ $$ = make_node (nod_def_field, (int) e_dfl_count,
$1, NULL, NULL, $3, NULL, NULL); }
;
output_proc_parameter($parameters)
: simple_column_def_name domain_or_non_array_type collate_clause
{ $parameters->add(ParameterClause($1, toName($3), NULL)); }
;
default_par_opt : DEFAULT begin_trigger default_value end_default
{ $$ = make_node (nod_def_default, (int) e_dft_count, $3, $4); }
@ -1954,14 +1955,14 @@ function_clause
;
function_clause_start
: symbol_UDF_name input_parameters
RETURNS
{ $<legacyField>$ = lex.g_field = make_field(NULL); }
: symbol_UDF_name
{ $$ = FB_NEW(getPool()) CreateAlterFunctionNode(getPool(), compilingText, toName($1)); }
input_parameters(&$2->parameters)
RETURNS { $<legacyField>$ = lex.g_field = make_field(NULL); }
domain_or_non_array_type collate_clause
{
$$ = FB_NEW(getPool()) CreateAlterFunctionNode(getPool(), compilingText, toName($1),
TypeClause($<legacyField>4, (dsql_str*) $6));
ParameterClause::fromLegacyParameterList($$->parameters, $2);
$$ = $2;
$$->returnType = TypeClause($<legacyField>5, toName($7));
}
;
@ -2574,15 +2575,16 @@ proc_outputs_opt : RETURNING_VALUES variable_list
/* EXECUTE BLOCK */
exec_block
: EXECUTE BLOCK block_input_params output_parameters AS
: EXECUTE BLOCK block_input_params
{ $<execBlockNode>$ = FB_NEW(getPool()) ExecBlockNode(getPool()); }
output_parameters(&$4->returns) AS
local_declaration_list
full_proc_block
{
ExecBlockNode* node = FB_NEW(getPool()) ExecBlockNode(getPool());
ExecBlockNode* node = $4;
node->legacyParameters = $3;
node->legacyReturns = $4;
node->localDeclList = $6;
node->body = $7;
node->localDeclList = $7;
node->body = $8;
$$ = node;
}
;
@ -2599,9 +2601,15 @@ block_parameters : block_parameter
{ $$ = make_node (nod_list, 2, $1, $3); }
;
block_parameter : proc_parameter '=' parameter
{ $$ = make_node (nod_param_val, e_prm_val_count, $1, $3); }
;
block_parameter
: block_proc_parameter '=' parameter
{ $$ = make_node (nod_param_val, e_prm_val_count, $1, $3); }
;
block_proc_parameter
: simple_column_def_name domain_or_non_array_type collate_clause
{ $$ = make_node (nod_def_field, (int) e_dfl_count, $1, NULL, NULL, $3, NULL, NULL); }
;
/* CREATE VIEW */
@ -6341,6 +6349,9 @@ static void stack_nodes (dsql_nod* node,
static Firebird::MetaName toName(dsql_nod* node)
{
if (!node)
return "";
dsql_str* str = (dsql_str*) node;
if (str->str_length > MAX_SQL_IDENTIFIER_LEN)

View File

@ -9784,14 +9784,11 @@ static dsql_nod* pass1_update_or_insert(CompiledStatement* statement, dsql_nod*
PASS1_resolve_variable_name
**/
dsql_nod* PASS1_resolve_variable_name(const dsql_nod* var_nodes, const dsql_str* var_name)
dsql_nod* PASS1_resolve_variable_name(const Array<dsql_nod*>& variables, const dsql_str* var_name)
{
dsql_nod* const* ptr = var_nodes->nod_arg;
dsql_nod* const* const end = ptr + var_nodes->nod_count;
for (; ptr < end; ptr++)
for (Array<dsql_nod*>::const_iterator i = variables.begin(); i != variables.end(); ++i)
{
dsql_nod* var_node = *ptr;
dsql_nod* var_node = *i;
if (var_node->nod_type == nod_variable)
{
const dsql_var* variable = (dsql_var*) var_node->nod_arg[e_var_variable];

View File

@ -28,7 +28,8 @@ void PASS1_check_unique_fields_names(Jrd::StrArray& names, const Jrd::dsql_nod*
Jrd::dsql_ctx* PASS1_make_context(Jrd::CompiledStatement* statement, const Jrd::dsql_nod* relation_node);
Jrd::dsql_nod* PASS1_node(Jrd::CompiledStatement*, Jrd::dsql_nod*);
Jrd::dsql_nod* PASS1_node_psql(Jrd::CompiledStatement*, Jrd::dsql_nod*, bool);
Jrd::dsql_nod* PASS1_resolve_variable_name(const Jrd::dsql_nod* var_nodes, const Jrd::dsql_str* var_name);
Jrd::dsql_nod* PASS1_resolve_variable_name(const Firebird::Array<Jrd::dsql_nod*>& variables,
const Jrd::dsql_str* var_name);
Jrd::dsql_nod* PASS1_rse(Jrd::CompiledStatement*, Jrd::dsql_nod*, Jrd::dsql_nod*);
Jrd::dsql_nod* PASS1_statement(Jrd::CompiledStatement*, Jrd::dsql_nod*);