mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 18:03:04 +01:00
Merge pull request #287 from red-soft-ru/B3_0_big_records_fix
Use rhd header for the last record fragment to fix wrong determination of the header size in get_header() function
This commit is contained in:
commit
dd349828e9
@ -3647,11 +3647,15 @@ static void store_big_record(thread_db* tdbb,
|
||||
RelationPages* relPages = rpb->rpb_relation->getPages(tdbb);
|
||||
PageNumber prior(relPages->rel_pg_space_id, 0);
|
||||
signed char count = 0;
|
||||
const USHORT max_data = dbb->dbb_page_size - (static_cast<USHORT>(sizeof(data_page)) + RHDF_SIZE);
|
||||
|
||||
// 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<USHORT>(sizeof(data_page)) + header_size);
|
||||
|
||||
// Fill up data pages tail first until what's left fits on a single page.
|
||||
|
||||
while (size > max_data)
|
||||
do
|
||||
{
|
||||
// Allocate and format data page and fragment header
|
||||
|
||||
@ -3660,14 +3664,23 @@ static void store_big_record(thread_db* tdbb,
|
||||
page->dpg_header.pag_flags = dpg_orphan | dpg_full;
|
||||
page->dpg_relation = rpb->rpb_relation->rel_id;
|
||||
page->dpg_count = 1;
|
||||
|
||||
// Cast to (rhdf*) but use only rhd fields for the last fragment
|
||||
rhdf* header = (rhdf*) & page->dpg_rpt[1];
|
||||
page->dpg_rpt[0].dpg_offset = (UCHAR *) header - (UCHAR *) page;
|
||||
page->dpg_rpt[0].dpg_length = max_data + RHDF_SIZE;
|
||||
header->rhdf_flags = (prior.getPageNum()) ? rhd_fragment | rhd_incomplete : rhd_fragment;
|
||||
header->rhdf_f_page = prior.getPageNum();
|
||||
page->dpg_rpt[0].dpg_length = max_data + header_size;
|
||||
header->rhdf_flags = rhd_fragment;
|
||||
|
||||
if (prior.getPageNum())
|
||||
{
|
||||
// This is not the last fragment
|
||||
header->rhdf_flags |= rhd_incomplete;
|
||||
header->rhdf_f_page = prior.getPageNum();
|
||||
}
|
||||
|
||||
USHORT length = max_data;
|
||||
size -= length;
|
||||
UCHAR* out = header->rhdf_data + length;
|
||||
UCHAR* out = (UCHAR *) header + page->dpg_rpt[0].dpg_length;
|
||||
|
||||
// Move compressed data onto page
|
||||
|
||||
@ -3722,7 +3735,11 @@ static void store_big_record(thread_db* tdbb,
|
||||
|
||||
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
|
||||
prior = rpb->getWindow(tdbb).win_page;
|
||||
}
|
||||
|
||||
// Other fragments except the last one should have rhdf header
|
||||
header_size = RHDF_SIZE;
|
||||
max_data = dbb->dbb_page_size - (static_cast<USHORT>(sizeof(data_page)) + header_size);
|
||||
} while (size > max_data);
|
||||
|
||||
// What's left fits on a page. Luckily, we don't have to store it ourselves.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user