diff --git a/src/dsql/PackageNodes.epp b/src/dsql/PackageNodes.epp index ae5b4a3981d..fc3975d9b82 100644 --- a/src/dsql/PackageNodes.epp +++ b/src/dsql/PackageNodes.epp @@ -474,6 +474,7 @@ void PackageReferenceNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc) jrd_tra* transaction = dsqlScratch->getTransaction(); thread_db* tdbb = JRD_get_thread_data(); *desc = ConstantValue::getDesc(tdbb, transaction, m_fullName); + desc->setNullable(true); } bool PackageReferenceNode::constantExists(thread_db* tdbb, Jrd::jrd_tra* transaction, @@ -503,6 +504,7 @@ bool PackageReferenceNode::constantExists(thread_db* tdbb, Jrd::jrd_tra* transac void PackageReferenceNode::getDesc(thread_db* tdbb, CompilerScratch*, dsc* desc) { *desc = ConstantValue::getDesc(tdbb, tdbb->getTransaction(), m_fullName); + desc->setNullable(true); } ValueExprNode* PackageReferenceNode::copy(thread_db* tdbb, NodeCopier& copier) const @@ -550,7 +552,6 @@ ValueExprNode* PackageReferenceNode::pass2(thread_db* tdbb, CompilerScratch* csb dsc* PackageReferenceNode::execute(thread_db* tdbb, Request* request) const { - impure_value* outputImpure = request->getImpure(m_impureOffset); switch (m_itemType) { case blr_pkg_reference_to_constant: @@ -558,7 +559,12 @@ dsc* PackageReferenceNode::execute(thread_db* tdbb, Request* request) const Package* package = m_package(request->getResources()); package->checkReload(tdbb); - EVL_make_value(tdbb, package->findConstant(m_fullName)->makeValue(tdbb, request), outputImpure); + dsc* constantDsc = package->findConstant(m_fullName)->makeValue(tdbb, request); + if (constantDsc == nullptr || constantDsc->isNull()) + return nullptr; + + impure_value* outputImpure = request->getImpure(m_impureOffset); + EVL_make_value(tdbb, constantDsc, outputImpure); return &outputImpure->vlu_desc; } default: diff --git a/src/dsql/parse.y b/src/dsql/parse.y index 8d66220d367..2790ed6209c 100644 --- a/src/dsql/parse.y +++ b/src/dsql/parse.y @@ -3338,10 +3338,11 @@ replace_package_body_clause %type package_const_item package_const_item - : symbol_package_const_name data_type_descriptor '=' value + : symbol_package_const_name data_type_descriptor collate_clause '=' value { - $$ = newNode(*$1, $2, $4); - $$->source = makeParseStr(YYPOSNARG(3), YYPOSNARG(4)); + setCollate($2, $3); + $$ = newNode(*$1, $2, $5); + $$->source = makeParseStr(YYPOSNARG(4), YYPOSNARG(5)); } ; diff --git a/src/jrd/Package.epp b/src/jrd/Package.epp index 48af17131ea..11727c15052 100644 --- a/src/jrd/Package.epp +++ b/src/jrd/Package.epp @@ -156,12 +156,12 @@ dsc* ConstantValue::makeValue(thread_db* tdbb, Request* request) { { ReadLockGuard guard(m_makeValueLock, FB_FUNCTION); - if (m_value.vlu_desc.dsc_address != nullptr) + if (m_value.vlu_desc.dsc_dtype != 0) return &m_value.vlu_desc; } WriteLockGuard guard(m_makeValueLock, FB_FUNCTION); - if (m_value.vlu_desc.dsc_address != nullptr) // Extra check in case of two callers waiting + if (m_value.vlu_desc.dsc_dtype != 0) // Extra check in case of two callers waiting return &m_value.vlu_desc; Attachment* attachment = tdbb->getAttachment(); @@ -196,14 +196,11 @@ dsc* ConstantValue::makeValue(thread_db* tdbb, Request* request) TRA_attach_request(tdbb->getTransaction(), request); - const dsc* temp = EVL_expr(tdbb, request, static_cast(csb->csb_node)); - EVL_make_value(tdbb, temp, &m_value, &getPool()); + //! Execute it here, while AutoSetRestore2 is active + executeCsbNode(tdbb, csb); } else - { - const dsc* temp = EVL_expr(tdbb, request, static_cast(csb->csb_node)); - EVL_make_value(tdbb, temp, &m_value, &getPool()); - } + executeCsbNode(tdbb, csb); } catch (const Exception& ex) { @@ -226,6 +223,23 @@ dsc* ConstantValue::makeValue(thread_db* tdbb, Request* request) return &m_value.vlu_desc; } +void ConstantValue::executeCsbNode(thread_db* tdbb, CompilerScratch* csb) +{ + ValueExprNode* exprNode = static_cast(csb->csb_node); + fb_assert(exprNode); + + const dsc* temp = EVL_expr(tdbb, tdbb->getRequest(), exprNode); + if (temp != nullptr) + { + EVL_make_value(tdbb, temp, &m_value, &getPool()); + } + else + { + exprNode->getDesc(tdbb, csb, &m_value.vlu_desc); + m_value.vlu_desc.setNull(); + } +} + ConstantValue& ConstantsCache::add(const QualifiedName& constName, const bool isPrivate) { fb_assert(!nameMap.exist(constName)); diff --git a/src/jrd/Package.h b/src/jrd/Package.h index 2be4b2c89b2..182b2823ce5 100644 --- a/src/jrd/Package.h +++ b/src/jrd/Package.h @@ -38,6 +38,7 @@ namespace Jrd { +class CompilerScratch; class DsqlCompilerScratch; class dsql_fld; @@ -84,6 +85,8 @@ class ConstantValue final : public Firebird::PermanentStorage dsc* makeValue(thread_db* tdbb, Request* request); private: + void executeCsbNode(thread_db* tdbb, CompilerScratch* csb); + // Lock in case of makeing value during the execute state Firebird::RWLock m_makeValueLock{};