From e93b31f9fc21cfd565bec148d00c00ae2d4a7a12 Mon Sep 17 00:00:00 2001 From: Artyom Abakumov Date: Tue, 16 Jun 2026 12:27:44 +0300 Subject: [PATCH 1/4] Check dsc_address missing instead of dsc_dtype and restore impure and using existing request --- src/jrd/Package.epp | 26 ++++++++++++++++++++++++-- src/jrd/Package.h | 1 + 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/jrd/Package.epp b/src/jrd/Package.epp index 405c22f416e..9fd0bb3b376 100644 --- a/src/jrd/Package.epp +++ b/src/jrd/Package.epp @@ -172,12 +172,12 @@ dsc* ConstantValue::makeValue(thread_db* tdbb, Request* request) { { ReadLockGuard guard(m_makeValueLock, FB_FUNCTION); - if (m_value.vlu_desc.dsc_dtype != dtype_unknown) + if (m_value.vlu_desc.dsc_address != nullptr) return &m_value.vlu_desc; } WriteLockGuard guard(m_makeValueLock, FB_FUNCTION); - if (m_value.vlu_desc.dsc_dtype != dtype_unknown) // Extra check in case of two callers waiting + if (m_value.vlu_desc.dsc_address != nullptr) // Extra check in case of two callers waiting return &m_value.vlu_desc; Attachment* attachment = tdbb->getAttachment(); @@ -196,6 +196,8 @@ dsc* ConstantValue::makeValue(thread_db* tdbb, Request* request) MET_parse_blob(tdbb, &name.schema, nullptr, &constantBid, &csb, nullptr, false, false); fb_assert(csb->csb_node != nullptr); + csb->csb_node->pass1(tdbb, csb); + csb->csb_node->pass2(tdbb, csb); if (request == nullptr) { @@ -216,7 +218,27 @@ dsc* ConstantValue::makeValue(thread_db* tdbb, Request* request) executeCsbNode(tdbb, csb); } else + { + // A csb->csb_node will use impureArea from the incoming request + // but it contains other data + // Backup the current data and restore it later + + // Reusing a small chunk is faster instead of makeing a new request + // And using existing space for a temporally value is better instead of adding this to request->impureArea + // and carrying it for whole request live + + const auto nodeImpureSize = csb->csb_impure; + if (request->impureArea.getCount() < nodeImpureSize) + request->impureArea.grow(nodeImpureSize - request->impureArea.getCount()); + + const Array backup(request->impureArea.begin(), nodeImpureSize); + + fb_assert(tdbb->getRequest() == request); executeCsbNode(tdbb, csb); + + // Restore + memcpy(request->impureArea.begin(), backup.begin(), nodeImpureSize); + } } catch (const Exception& ex) { diff --git a/src/jrd/Package.h b/src/jrd/Package.h index 182b2823ce5..1a4697e95a0 100644 --- a/src/jrd/Package.h +++ b/src/jrd/Package.h @@ -73,6 +73,7 @@ class ConstantValue final : public Firebird::PermanentStorage delete m_value.vlu_string; m_value = {}; m_value.vlu_desc = typeDesc; + m_value.vlu_desc.dsc_address = nullptr; // Make sure to call makeValue } void updateValue(const bid blobId) From a2aad6420904ba2867c6b69fd1c6183d9df42f34 Mon Sep 17 00:00:00 2001 From: Artyom Abakumov Date: Sun, 21 Jun 2026 11:23:56 +0300 Subject: [PATCH 2/4] Use correct way to use csb_impure --- src/jrd/Package.epp | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/jrd/Package.epp b/src/jrd/Package.epp index 9fd0bb3b376..e82d8d254eb 100644 --- a/src/jrd/Package.epp +++ b/src/jrd/Package.epp @@ -195,10 +195,18 @@ dsc* ConstantValue::makeValue(thread_db* tdbb, Request* request) bid constantBid = getBlobId(tdbb); MET_parse_blob(tdbb, &name.schema, nullptr, &constantBid, &csb, nullptr, false, false); + if (request != nullptr) + { + // Allocate new impure data in a correct position + csb->csb_impure = request->impureArea.getCount(); + } + fb_assert(csb->csb_node != nullptr); csb->csb_node->pass1(tdbb, csb); csb->csb_node->pass2(tdbb, csb); + // request is null when this function called inside Package::scan (without MINISCAN) + // request is not null when this function called in PackageReferenceNode::execute if (request == nullptr) { // Came from Reload @@ -219,25 +227,13 @@ dsc* ConstantValue::makeValue(thread_db* tdbb, Request* request) } else { - // A csb->csb_node will use impureArea from the incoming request - // but it contains other data - // Backup the current data and restore it later - - // Reusing a small chunk is faster instead of makeing a new request - // And using existing space for a temporally value is better instead of adding this to request->impureArea - // and carrying it for whole request live - - const auto nodeImpureSize = csb->csb_impure; - if (request->impureArea.getCount() < nodeImpureSize) - request->impureArea.grow(nodeImpureSize - request->impureArea.getCount()); - - const Array backup(request->impureArea.begin(), nodeImpureSize); - + if (csb->csb_impure > request->impureArea.getCount()) + { + // impureArea does not automatically extend. Do it manually + request->impureArea.grow(csb->csb_impure); + } fb_assert(tdbb->getRequest() == request); executeCsbNode(tdbb, csb); - - // Restore - memcpy(request->impureArea.begin(), backup.begin(), nodeImpureSize); } } catch (const Exception& ex) From f92e411d8d0b145472811de1dd4d949d02817560 Mon Sep 17 00:00:00 2001 From: Artyom Abakumov Date: Mon, 22 Jun 2026 15:28:43 +0300 Subject: [PATCH 3/4] Always use handmade stmt and request to make constant value --- src/dsql/PackageNodes.epp | 2 +- src/jrd/Package.epp | 51 +++++++++++---------------------------- src/jrd/Package.h | 2 +- 3 files changed, 16 insertions(+), 39 deletions(-) diff --git a/src/dsql/PackageNodes.epp b/src/dsql/PackageNodes.epp index dd57836cdc7..4825ad6efb7 100644 --- a/src/dsql/PackageNodes.epp +++ b/src/dsql/PackageNodes.epp @@ -560,7 +560,7 @@ dsc* PackageReferenceNode::execute(thread_db* tdbb, Request* request) const Package* package = m_package(request->getResources()); package->checkReload(tdbb); - dsc* constantDsc = package->findConstant(m_fullName)->makeValue(tdbb, request); + dsc* constantDsc = package->findConstant(m_fullName)->makeValue(tdbb); if (constantDsc == nullptr || constantDsc->isNull()) return nullptr; diff --git a/src/jrd/Package.epp b/src/jrd/Package.epp index e82d8d254eb..ce7e797ced3 100644 --- a/src/jrd/Package.epp +++ b/src/jrd/Package.epp @@ -168,7 +168,7 @@ bid ConstantValue::getBlobId(thread_db* tdbb) return m_blrBlobId.isEmpty() ? getConstantBid(tdbb, name) : m_blrBlobId; } -dsc* ConstantValue::makeValue(thread_db* tdbb, Request* request) +dsc* ConstantValue::makeValue(thread_db* tdbb) { { ReadLockGuard guard(m_makeValueLock, FB_FUNCTION); @@ -184,6 +184,7 @@ dsc* ConstantValue::makeValue(thread_db* tdbb, Request* request) MemoryPool* csb_pool = attachment->att_database->createPool(); Statement* handmadeStmt = nullptr; + Request* request = nullptr; try { ContextPoolHolder context(tdbb, csb_pool); @@ -195,46 +196,22 @@ dsc* ConstantValue::makeValue(thread_db* tdbb, Request* request) bid constantBid = getBlobId(tdbb); MET_parse_blob(tdbb, &name.schema, nullptr, &constantBid, &csb, nullptr, false, false); - if (request != nullptr) - { - // Allocate new impure data in a correct position - csb->csb_impure = request->impureArea.getCount(); - } - fb_assert(csb->csb_node != nullptr); - csb->csb_node->pass1(tdbb, csb); - csb->csb_node->pass2(tdbb, csb); - - // request is null when this function called inside Package::scan (without MINISCAN) - // request is not null when this function called in PackageReferenceNode::execute - if (request == nullptr) - { - // Came from Reload - handmadeStmt = Statement::makeStatement(tdbb, csb, true); - request = handmadeStmt->makeRootRequest(tdbb); + // Came from Reload + handmadeStmt = Statement::makeStatement(tdbb, csb, true); + request = handmadeStmt->makeRootRequest(tdbb); - AutoSetRestore2 autoSetRequest( - tdbb, &thread_db::getRequest, &thread_db::setRequest, request); + AutoSetRestore2 autoSetRequest( + tdbb, &thread_db::getRequest, &thread_db::setRequest, request); - request->setUsed(); - request->setAttachment(attachment); - attachment->att_requests.add(request); + request->setUsed(); + request->setAttachment(attachment); + attachment->att_requests.add(request); - TRA_attach_request(tdbb->getTransaction(), request); + TRA_attach_request(tdbb->getTransaction(), request); - // Execute it here, while AutoSetRestore2 is active - executeCsbNode(tdbb, csb); - } - else - { - if (csb->csb_impure > request->impureArea.getCount()) - { - // impureArea does not automatically extend. Do it manually - request->impureArea.grow(csb->csb_impure); - } - fb_assert(tdbb->getRequest() == request); - executeCsbNode(tdbb, csb); - } + // Execute it while AutoSetRestore2 is active + executeCsbNode(tdbb, csb); } catch (const Exception& ex) { @@ -444,7 +421,7 @@ ConstantValue& Package::addConstant(thread_db* tdbb, auto& value = constants.add(constName, isPrivate); value.updateValue(blrBlobId); if (!skipMakeValue) - value.makeValue(tdbb, nullptr); + value.makeValue(tdbb); return value; } diff --git a/src/jrd/Package.h b/src/jrd/Package.h index 1a4697e95a0..55238685383 100644 --- a/src/jrd/Package.h +++ b/src/jrd/Package.h @@ -83,7 +83,7 @@ class ConstantValue final : public Firebird::PermanentStorage bid getBlobId(thread_db* tdbb); - dsc* makeValue(thread_db* tdbb, Request* request); + dsc* makeValue(thread_db* tdbb); private: void executeCsbNode(thread_db* tdbb, CompilerScratch* csb); From 36595a3c2a6483717656bab2504eceec9e72fb27 Mon Sep 17 00:00:00 2001 From: Artyom Abakumov Date: Mon, 22 Jun 2026 15:48:19 +0300 Subject: [PATCH 4/4] Remove irrelevant Package Constant comments --- src/jrd/Package.epp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/jrd/Package.epp b/src/jrd/Package.epp index ce7e797ced3..aa441c32930 100644 --- a/src/jrd/Package.epp +++ b/src/jrd/Package.epp @@ -197,7 +197,6 @@ dsc* ConstantValue::makeValue(thread_db* tdbb) MET_parse_blob(tdbb, &name.schema, nullptr, &constantBid, &csb, nullptr, false, false); - // Came from Reload handmadeStmt = Statement::makeStatement(tdbb, csb, true); request = handmadeStmt->makeRootRequest(tdbb); @@ -342,7 +341,7 @@ ScanResult Package::scan(thread_db* tdbb, ObjectBase::Flag flags) skipMakeValue); if (skipMakeValue) - this->m_callReload = true; // Value is necessary for to calculate hash + this->m_callReload = true; } END_FOR }