diff --git a/src/dsql/DdlNodes.epp b/src/dsql/DdlNodes.epp index b349e8d1f6..d156e11fe1 100644 --- a/src/dsql/DdlNodes.epp +++ b/src/dsql/DdlNodes.epp @@ -1661,6 +1661,7 @@ string CreateAlterFunctionNode::internalPrint(NodePrinter& printer) const DdlNode* CreateAlterFunctionNode::dsqlPass(DsqlCompilerScratch* dsqlScratch) { dsqlScratch->flags |= (DsqlCompilerScratch::FLAG_BLOCK | DsqlCompilerScratch::FLAG_FUNCTION); + dsqlScratch->reserveInitialVarNumbers(1); LocalDeclarationsNode::checkUniqueFieldsNames(localDeclList, ¶meters, nullptr); @@ -2677,6 +2678,7 @@ string CreateAlterProcedureNode::internalPrint(NodePrinter& printer) const DdlNode* CreateAlterProcedureNode::dsqlPass(DsqlCompilerScratch* dsqlScratch) { dsqlScratch->flags |= (DsqlCompilerScratch::FLAG_BLOCK | DsqlCompilerScratch::FLAG_PROCEDURE); + dsqlScratch->reserveInitialVarNumbers(returns.getCount()); LocalDeclarationsNode::checkUniqueFieldsNames(localDeclList, ¶meters, &returns); diff --git a/src/dsql/DsqlCompilerScratch.cpp b/src/dsql/DsqlCompilerScratch.cpp index 048e3c0b02..586dfdb9ee 100644 --- a/src/dsql/DsqlCompilerScratch.cpp +++ b/src/dsql/DsqlCompilerScratch.cpp @@ -298,8 +298,6 @@ void DsqlCompilerScratch::putLocalVariableDecl(dsql_var* variable, DeclareVariab if (variable->field->fld_name.hasData()) // Not a function return value putDebugVariable(variable->number, variable->field->fld_name); - ++hiddenVarsNumber; - if (variable->type != dsql_var::TYPE_INPUT && hostParam && hostParam->dsqlDef->defaultClause) { hostParam->dsqlDef->defaultClause->value = @@ -377,7 +375,7 @@ void DsqlCompilerScratch::putOuterMaps() // Make a variable. 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 localNumber) { DEV_BLKCHK(field, dsql_type_fld); @@ -387,7 +385,7 @@ dsql_var* DsqlCompilerScratch::makeVariable(dsql_fld* field, const char* name, dsqlVar->type = type; dsqlVar->msgNumber = msgNumber; dsqlVar->msgItem = itemNumber; - dsqlVar->number = localNumber; + dsqlVar->number = localNumber.has_value() ? localNumber.value() : nextVarNumber++; dsqlVar->field = field; if (field) diff --git a/src/dsql/DsqlCompilerScratch.h b/src/dsql/DsqlCompilerScratch.h index 8b63f4cb2d..8755b7cb2d 100644 --- a/src/dsql/DsqlCompilerScratch.h +++ b/src/dsql/DsqlCompilerScratch.h @@ -30,6 +30,7 @@ #include "../jrd/MetaName.h" #include "../common/classes/stack.h" #include "../common/classes/alloc.h" +#include namespace Jrd { @@ -164,7 +165,7 @@ public: void putOuterMaps(); dsql_var* makeVariable(dsql_fld*, const char*, const dsql_var::Type type, USHORT, - USHORT, USHORT); + USHORT, std::optional = std::nullopt); dsql_var* resolveVariable(const MetaName& varName); void genReturn(bool eosFlag = false); @@ -178,8 +179,7 @@ public: context->clear(); contextNumber = 0; derivedContextNumber = 0; - - hiddenVarsNumber = 0; + nextVarNumber = 0; 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; } void setPsql(bool value) { psql = value; } @@ -298,7 +309,6 @@ public: bool processingWindow = false; // processing window functions bool checkConstraintTrigger = false; // compiling a check constraint trigger dsc domainValue; // VALUE in the context of domain's check constraint - USHORT hiddenVarsNumber = 0; // next hidden variable number Firebird::Array hiddenVariables; // hidden variables Firebird::Array variables; Firebird::Array outputVariables; @@ -311,6 +321,7 @@ public: private: Firebird::HalfStaticArray ctes; // common table expressions Firebird::HalfStaticArray cteAliases; // CTE aliases in recursive members + USHORT nextVarNumber = 0; // Next available variable number bool psql = false; Firebird::LeftPooledMap subFunctions; Firebird::LeftPooledMap subProcedures; diff --git a/src/dsql/ExprNodes.cpp b/src/dsql/ExprNodes.cpp index 34eafc9d56..34fcb954e0 100644 --- a/src/dsql/ExprNodes.cpp +++ b/src/dsql/ExprNodes.cpp @@ -13991,7 +13991,7 @@ ValueExprNode* VariableNode::dsqlPass(DsqlCompilerScratch* dsqlScratch) else { if (!dsqlScratch->outerVarsMap.exist(node->dsqlVar->number)) - dsqlScratch->outerVarsMap.put(node->dsqlVar->number, dsqlScratch->hiddenVarsNumber++); + dsqlScratch->outerVarsMap.put(node->dsqlVar->number, dsqlScratch->reserveVarNumber()); } } } diff --git a/src/dsql/StmtNodes.cpp b/src/dsql/StmtNodes.cpp index ff2bb68b1a..e6f9351f1d 100644 --- a/src/dsql/StmtNodes.cpp +++ b/src/dsql/StmtNodes.cpp @@ -4950,6 +4950,7 @@ ExecBlockNode* ExecBlockNode::dsqlPass(DsqlCompilerScratch* dsqlScratch) statement->setType(DsqlStatement::TYPE_EXEC_BLOCK); dsqlScratch->flags |= DsqlCompilerScratch::FLAG_BLOCK; + dsqlScratch->reserveInitialVarNumbers(parameters.getCount() + returns.getCount()); 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. const bool isSubRoutine = dsqlScratch->flags & DsqlCompilerScratch::FLAG_SUB_ROUTINE; const auto& variables = isSubRoutine ? dsqlScratch->outputVariables : dsqlScratch->variables; - USHORT locals = variables.getCount(); Array declaredVariables; @@ -6160,7 +6160,7 @@ void LocalDeclarationsNode::genBlr(DsqlCompilerScratch* dsqlScratch) } 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); 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 // the descriptor. DsqlDescMaker::fromField(&variable->desc, field); - - ++locals; } else if (nodeIs(parameter) || nodeIs(parameter) || @@ -10982,8 +10980,7 @@ static VariableNode* dsqlPassHiddenVariable(DsqlCompilerScratch* dsqlScratch, Va } VariableNode* varNode = FB_NEW_POOL(*tdbb->getDefaultPool()) VariableNode(*tdbb->getDefaultPool()); - varNode->dsqlVar = dsqlScratch->makeVariable(NULL, "", dsql_var::TYPE_HIDDEN, - 0, 0, dsqlScratch->hiddenVarsNumber++); + varNode->dsqlVar = dsqlScratch->makeVariable(nullptr, "", dsql_var::TYPE_HIDDEN, 0, 0); DsqlDescMaker::fromNode(dsqlScratch, &varNode->dsqlVar->desc, expr); varNode->setDsqlDesc(varNode->dsqlVar->desc);