diff --git a/src/dsql/PackageNodes.epp b/src/dsql/PackageNodes.epp index ae5b4a3981d..7fb168e7857 100644 --- a/src/dsql/PackageNodes.epp +++ b/src/dsql/PackageNodes.epp @@ -550,7 +550,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 +557,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..77ff63bd2e3 100644 --- a/src/jrd/Package.epp +++ b/src/jrd/Package.epp @@ -52,7 +52,7 @@ DATABASE DB = FILENAME "ODS.RDB"; bool ConstantValue::hash(thread_db* tdbb, Firebird::sha512& digest) const { - fb_assert(m_value.vlu_desc.dsc_dtype != 0); + fb_assert(m_value.vlu_desc.dsc_dtype != dtype_unknown); digest.process(sizeof(m_value.vlu_desc), &m_value.vlu_desc); return true; @@ -84,8 +84,10 @@ dsc ConstantValue::getDesc(thread_db* tdbb, Jrd::jrd_tra* transaction, const Qua CSetId(FLD.RDB$CHARACTER_SET_ID), CollId(FLD.RDB$COLLATION_ID)); - if (!succeed) - (Arg::Gds(isc_bad_constant_desc) << Arg::Str(name.toQuotedString())).raise(); + if (!succeed) + (Arg::Gds(isc_bad_constant_desc) << Arg::Str(name.toQuotedString())).raise(); + + desc.setNullable(FLD.RDB$NULL_FLAG.NULL || FLD.RDB$NULL_FLAG == 0); } END_FOR @@ -156,12 +158,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 != dtype_unknown) 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 != dtype_unknown) // Extra check in case of two callers waiting return &m_value.vlu_desc; Attachment* attachment = tdbb->getAttachment(); @@ -196,14 +198,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 +225,23 @@ dsc* ConstantValue::makeValue(thread_db* tdbb, Request* request) return &m_value.vlu_desc; } +void ConstantValue::executeCsbNode(thread_db* tdbb, CompilerScratch* csb) +{ + fb_assert(csb->csb_node && csb->csb_node->getKind() == DmlNode::KIND_VALUE); + ValueExprNode* exprNode = static_cast(csb->csb_node); + + 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{};