From 4274ee42cb1f843e3c123a33c662521f496868f5 Mon Sep 17 00:00:00 2001 From: Artyom Ivanov Date: Mon, 26 Oct 2026 17:48:02 +0300 Subject: [PATCH 1/2] fix(dpm): Handle case where big record cannot be stored on single page with RHDE header, but with RHD it can be stored --- src/jrd/dpm.epp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/jrd/dpm.epp b/src/jrd/dpm.epp index 083e9cfddb0..e2b72b97aa4 100644 --- a/src/jrd/dpm.epp +++ b/src/jrd/dpm.epp @@ -3716,7 +3716,10 @@ static void store_big_record(thread_db* tdbb, // The last fragment should have rhd header because rhd_incomplete flag won't be set for it. // It's important for get_header() function which relies on rhd_incomplete flag to determine header size. FB_SIZE_T header_size = RHD_SIZE; - USHORT max_data = dbb->dbb_page_size - (static_cast(sizeof(data_page)) + header_size); + // We can have a big record that is not fitting into single page with RHDE header, but with RHD header + // it does fit into single page, so to handle such case use `size` as maximum possible data, write whole + // data in tail with RHD, and create head with no data at all. + USHORT max_data = MIN(dbb->dbb_page_size - (static_cast(sizeof(data_page)) + header_size), size); // Fill up data pages tail first until what's left fits on a single page. From a16560ecb7810f11cec71326b6f8cd3ebea00789 Mon Sep 17 00:00:00 2001 From: Artyom Ivanov Date: Tue, 27 Oct 2026 09:42:14 +0300 Subject: [PATCH 2/2] fix(gstat): Use correct record header according to record flags --- src/utilities/gstat/dba.epp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/utilities/gstat/dba.epp b/src/utilities/gstat/dba.epp index a1ff5701a1c..a10a382febd 100644 --- a/src/utilities/gstat/dba.epp +++ b/src/utilities/gstat/dba.epp @@ -1434,6 +1434,10 @@ static bool analyze_data_page( dba_rel* relation, const data_page* page, bool sw relation->rel_record_space -= RHDF_SIZE; relation->rel_record_space += analyze_fragments(relation, header); } + else if (header->rhdf_flags & rhd_long_tranum) + { + relation->rel_record_space -= RHDE_SIZE; + } else { relation->rel_record_space -= RHD_SIZE; @@ -1538,10 +1542,16 @@ static ULONG analyze_fragments(dba_rel* relation, const rhdf* header) const data_page::dpg_repeat* index = &page->dpg_rpt[f_line]; if (!index->dpg_offset) break; - space += index->dpg_length; - space -= RHDF_SIZE; header = (const rhdf*) ((SCHAR *) page + index->dpg_offset); + space += index->dpg_length; + if (header->rhdf_flags & rhd_incomplete) + space -= RHDF_SIZE; + else if (header->rhdf_flags & rhd_long_tranum) + space -= RHDE_SIZE; + else + space -= RHD_SIZE; + fragments++; } @@ -1741,6 +1751,8 @@ static ULONG analyze_versions( dba_rel* relation, const rhdf* header) space -= RHDF_SIZE; space += analyze_fragments(relation, header); } + else if (header->rhdf_flags & rhd_long_tranum) + space -= RHDE_SIZE; else space -= RHD_SIZE; }