mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 22:43:03 +01:00
Fix #7931 - Incorrect variable usage using UPDATE OR INSERT.
This commit is contained in:
parent
78ff27df5e
commit
305c40a05b
@ -1661,6 +1661,7 @@ string CreateAlterFunctionNode::internalPrint(NodePrinter& printer) const
|
|||||||
DdlNode* CreateAlterFunctionNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
DdlNode* CreateAlterFunctionNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||||
{
|
{
|
||||||
dsqlScratch->flags |= (DsqlCompilerScratch::FLAG_BLOCK | DsqlCompilerScratch::FLAG_FUNCTION);
|
dsqlScratch->flags |= (DsqlCompilerScratch::FLAG_BLOCK | DsqlCompilerScratch::FLAG_FUNCTION);
|
||||||
|
dsqlScratch->reserveInitialVarNumbers(1);
|
||||||
|
|
||||||
LocalDeclarationsNode::checkUniqueFieldsNames(localDeclList, ¶meters, nullptr);
|
LocalDeclarationsNode::checkUniqueFieldsNames(localDeclList, ¶meters, nullptr);
|
||||||
|
|
||||||
@ -2677,6 +2678,7 @@ string CreateAlterProcedureNode::internalPrint(NodePrinter& printer) const
|
|||||||
DdlNode* CreateAlterProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
DdlNode* CreateAlterProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||||
{
|
{
|
||||||
dsqlScratch->flags |= (DsqlCompilerScratch::FLAG_BLOCK | DsqlCompilerScratch::FLAG_PROCEDURE);
|
dsqlScratch->flags |= (DsqlCompilerScratch::FLAG_BLOCK | DsqlCompilerScratch::FLAG_PROCEDURE);
|
||||||
|
dsqlScratch->reserveInitialVarNumbers(returns.getCount());
|
||||||
|
|
||||||
LocalDeclarationsNode::checkUniqueFieldsNames(localDeclList, ¶meters, &returns);
|
LocalDeclarationsNode::checkUniqueFieldsNames(localDeclList, ¶meters, &returns);
|
||||||
|
|
||||||
|
@ -298,8 +298,6 @@ void DsqlCompilerScratch::putLocalVariableDecl(dsql_var* variable, DeclareVariab
|
|||||||
if (variable->field->fld_name.hasData()) // Not a function return value
|
if (variable->field->fld_name.hasData()) // Not a function return value
|
||||||
putDebugVariable(variable->number, variable->field->fld_name);
|
putDebugVariable(variable->number, variable->field->fld_name);
|
||||||
|
|
||||||
++hiddenVarsNumber;
|
|
||||||
|
|
||||||
if (variable->type != dsql_var::TYPE_INPUT && hostParam && hostParam->dsqlDef->defaultClause)
|
if (variable->type != dsql_var::TYPE_INPUT && hostParam && hostParam->dsqlDef->defaultClause)
|
||||||
{
|
{
|
||||||
hostParam->dsqlDef->defaultClause->value =
|
hostParam->dsqlDef->defaultClause->value =
|
||||||
@ -377,7 +375,7 @@ void DsqlCompilerScratch::putOuterMaps()
|
|||||||
|
|
||||||
// Make a variable.
|
// Make a variable.
|
||||||
dsql_var* DsqlCompilerScratch::makeVariable(dsql_fld* field, const char* name,
|
dsql_var* DsqlCompilerScratch::makeVariable(dsql_fld* field, const char* name,
|
||||||
const dsql_var::Type type, USHORT msgNumber, USHORT itemNumber, USHORT localNumber)
|
const dsql_var::Type type, USHORT msgNumber, USHORT itemNumber, std::optional<USHORT> localNumber)
|
||||||
{
|
{
|
||||||
DEV_BLKCHK(field, dsql_type_fld);
|
DEV_BLKCHK(field, dsql_type_fld);
|
||||||
|
|
||||||
@ -387,7 +385,7 @@ dsql_var* DsqlCompilerScratch::makeVariable(dsql_fld* field, const char* name,
|
|||||||
dsqlVar->type = type;
|
dsqlVar->type = type;
|
||||||
dsqlVar->msgNumber = msgNumber;
|
dsqlVar->msgNumber = msgNumber;
|
||||||
dsqlVar->msgItem = itemNumber;
|
dsqlVar->msgItem = itemNumber;
|
||||||
dsqlVar->number = localNumber;
|
dsqlVar->number = localNumber.has_value() ? localNumber.value() : nextVarNumber++;
|
||||||
dsqlVar->field = field;
|
dsqlVar->field = field;
|
||||||
|
|
||||||
if (field)
|
if (field)
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "../jrd/MetaName.h"
|
#include "../jrd/MetaName.h"
|
||||||
#include "../common/classes/stack.h"
|
#include "../common/classes/stack.h"
|
||||||
#include "../common/classes/alloc.h"
|
#include "../common/classes/alloc.h"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace Jrd
|
namespace Jrd
|
||||||
{
|
{
|
||||||
@ -164,7 +165,7 @@ public:
|
|||||||
|
|
||||||
void putOuterMaps();
|
void putOuterMaps();
|
||||||
dsql_var* makeVariable(dsql_fld*, const char*, const dsql_var::Type type, USHORT,
|
dsql_var* makeVariable(dsql_fld*, const char*, const dsql_var::Type type, USHORT,
|
||||||
USHORT, USHORT);
|
USHORT, std::optional<USHORT> = std::nullopt);
|
||||||
dsql_var* resolveVariable(const MetaName& varName);
|
dsql_var* resolveVariable(const MetaName& varName);
|
||||||
void genReturn(bool eosFlag = false);
|
void genReturn(bool eosFlag = false);
|
||||||
|
|
||||||
@ -178,8 +179,7 @@ public:
|
|||||||
context->clear();
|
context->clear();
|
||||||
contextNumber = 0;
|
contextNumber = 0;
|
||||||
derivedContextNumber = 0;
|
derivedContextNumber = 0;
|
||||||
|
nextVarNumber = 0;
|
||||||
hiddenVarsNumber = 0;
|
|
||||||
hiddenVariables.clear();
|
hiddenVariables.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,6 +234,17 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
USHORT reserveVarNumber()
|
||||||
|
{
|
||||||
|
return nextVarNumber++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserveInitialVarNumbers(USHORT count)
|
||||||
|
{
|
||||||
|
fb_assert(nextVarNumber == 0);
|
||||||
|
nextVarNumber = count;
|
||||||
|
}
|
||||||
|
|
||||||
bool isPsql() const { return psql; }
|
bool isPsql() const { return psql; }
|
||||||
void setPsql(bool value) { psql = value; }
|
void setPsql(bool value) { psql = value; }
|
||||||
|
|
||||||
@ -298,7 +309,6 @@ public:
|
|||||||
bool processingWindow = false; // processing window functions
|
bool processingWindow = false; // processing window functions
|
||||||
bool checkConstraintTrigger = false; // compiling a check constraint trigger
|
bool checkConstraintTrigger = false; // compiling a check constraint trigger
|
||||||
dsc domainValue; // VALUE in the context of domain's check constraint
|
dsc domainValue; // VALUE in the context of domain's check constraint
|
||||||
USHORT hiddenVarsNumber = 0; // next hidden variable number
|
|
||||||
Firebird::Array<dsql_var*> hiddenVariables; // hidden variables
|
Firebird::Array<dsql_var*> hiddenVariables; // hidden variables
|
||||||
Firebird::Array<dsql_var*> variables;
|
Firebird::Array<dsql_var*> variables;
|
||||||
Firebird::Array<dsql_var*> outputVariables;
|
Firebird::Array<dsql_var*> outputVariables;
|
||||||
@ -311,6 +321,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
Firebird::HalfStaticArray<SelectExprNode*, 4> ctes; // common table expressions
|
Firebird::HalfStaticArray<SelectExprNode*, 4> ctes; // common table expressions
|
||||||
Firebird::HalfStaticArray<const Firebird::string*, 4> cteAliases; // CTE aliases in recursive members
|
Firebird::HalfStaticArray<const Firebird::string*, 4> cteAliases; // CTE aliases in recursive members
|
||||||
|
USHORT nextVarNumber = 0; // Next available variable number
|
||||||
bool psql = false;
|
bool psql = false;
|
||||||
Firebird::LeftPooledMap<MetaName, DeclareSubFuncNode*> subFunctions;
|
Firebird::LeftPooledMap<MetaName, DeclareSubFuncNode*> subFunctions;
|
||||||
Firebird::LeftPooledMap<MetaName, DeclareSubProcNode*> subProcedures;
|
Firebird::LeftPooledMap<MetaName, DeclareSubProcNode*> subProcedures;
|
||||||
|
@ -13991,7 +13991,7 @@ ValueExprNode* VariableNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!dsqlScratch->outerVarsMap.exist(node->dsqlVar->number))
|
if (!dsqlScratch->outerVarsMap.exist(node->dsqlVar->number))
|
||||||
dsqlScratch->outerVarsMap.put(node->dsqlVar->number, dsqlScratch->hiddenVarsNumber++);
|
dsqlScratch->outerVarsMap.put(node->dsqlVar->number, dsqlScratch->reserveVarNumber());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4950,6 +4950,7 @@ ExecBlockNode* ExecBlockNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
|||||||
statement->setType(DsqlStatement::TYPE_EXEC_BLOCK);
|
statement->setType(DsqlStatement::TYPE_EXEC_BLOCK);
|
||||||
|
|
||||||
dsqlScratch->flags |= DsqlCompilerScratch::FLAG_BLOCK;
|
dsqlScratch->flags |= DsqlCompilerScratch::FLAG_BLOCK;
|
||||||
|
dsqlScratch->reserveInitialVarNumbers(parameters.getCount() + returns.getCount());
|
||||||
|
|
||||||
ExecBlockNode* node = FB_NEW_POOL(dsqlScratch->getPool()) ExecBlockNode(dsqlScratch->getPool());
|
ExecBlockNode* node = FB_NEW_POOL(dsqlScratch->getPool()) ExecBlockNode(dsqlScratch->getPool());
|
||||||
|
|
||||||
@ -6128,7 +6129,6 @@ void LocalDeclarationsNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
|||||||
// Sub routine doesn't need ports and should generate BLR as declared in its metadata.
|
// Sub routine doesn't need ports and should generate BLR as declared in its metadata.
|
||||||
const bool isSubRoutine = dsqlScratch->flags & DsqlCompilerScratch::FLAG_SUB_ROUTINE;
|
const bool isSubRoutine = dsqlScratch->flags & DsqlCompilerScratch::FLAG_SUB_ROUTINE;
|
||||||
const auto& variables = isSubRoutine ? dsqlScratch->outputVariables : dsqlScratch->variables;
|
const auto& variables = isSubRoutine ? dsqlScratch->outputVariables : dsqlScratch->variables;
|
||||||
USHORT locals = variables.getCount();
|
|
||||||
|
|
||||||
Array<dsql_var*> declaredVariables;
|
Array<dsql_var*> declaredVariables;
|
||||||
|
|
||||||
@ -6160,7 +6160,7 @@ void LocalDeclarationsNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const auto variable = dsqlScratch->makeVariable(field, field->fld_name.c_str(),
|
const auto variable = dsqlScratch->makeVariable(field, field->fld_name.c_str(),
|
||||||
dsql_var::TYPE_LOCAL, 0, 0, locals);
|
dsql_var::TYPE_LOCAL, 0, 0);
|
||||||
declaredVariables.add(variable);
|
declaredVariables.add(variable);
|
||||||
|
|
||||||
dsqlScratch->putLocalVariableDecl(variable, varNode, varNode->dsqlDef->type->collate);
|
dsqlScratch->putLocalVariableDecl(variable, varNode, varNode->dsqlDef->type->collate);
|
||||||
@ -6168,8 +6168,6 @@ void LocalDeclarationsNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
|||||||
// Some field attributes are calculated inside putLocalVariable(), so we reinitialize
|
// Some field attributes are calculated inside putLocalVariable(), so we reinitialize
|
||||||
// the descriptor.
|
// the descriptor.
|
||||||
DsqlDescMaker::fromField(&variable->desc, field);
|
DsqlDescMaker::fromField(&variable->desc, field);
|
||||||
|
|
||||||
++locals;
|
|
||||||
}
|
}
|
||||||
else if (nodeIs<DeclareCursorNode>(parameter) ||
|
else if (nodeIs<DeclareCursorNode>(parameter) ||
|
||||||
nodeIs<DeclareSubProcNode>(parameter) ||
|
nodeIs<DeclareSubProcNode>(parameter) ||
|
||||||
@ -10982,8 +10980,7 @@ static VariableNode* dsqlPassHiddenVariable(DsqlCompilerScratch* dsqlScratch, Va
|
|||||||
}
|
}
|
||||||
|
|
||||||
VariableNode* varNode = FB_NEW_POOL(*tdbb->getDefaultPool()) VariableNode(*tdbb->getDefaultPool());
|
VariableNode* varNode = FB_NEW_POOL(*tdbb->getDefaultPool()) VariableNode(*tdbb->getDefaultPool());
|
||||||
varNode->dsqlVar = dsqlScratch->makeVariable(NULL, "", dsql_var::TYPE_HIDDEN,
|
varNode->dsqlVar = dsqlScratch->makeVariable(nullptr, "", dsql_var::TYPE_HIDDEN, 0, 0);
|
||||||
0, 0, dsqlScratch->hiddenVarsNumber++);
|
|
||||||
|
|
||||||
DsqlDescMaker::fromNode(dsqlScratch, &varNode->dsqlVar->desc, expr);
|
DsqlDescMaker::fromNode(dsqlScratch, &varNode->dsqlVar->desc, expr);
|
||||||
varNode->setDsqlDesc(varNode->dsqlVar->desc);
|
varNode->setDsqlDesc(varNode->dsqlVar->desc);
|
||||||
|
Loading…
Reference in New Issue
Block a user