mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-24 03:23:03 +01:00
Fix "no current record .." bug when an undependent stream A is dependent on stream B and B is dependent on stream C.
Stream A was merged with the stream C and only B was correctly joined.
This commit is contained in:
parent
c749838d31
commit
b9456e4747
112
src/jrd/opt.cpp
112
src/jrd/opt.cpp
@ -755,65 +755,73 @@ RecordSource* OPT_compile(thread_db* tdbb,
|
|||||||
|
|
||||||
fb_assert(streams[0] != 1 || csb->csb_rpt[streams[1]].csb_relation != 0);
|
fb_assert(streams[0] != 1 || csb->csb_rpt[streams[1]].csb_relation != 0);
|
||||||
|
|
||||||
// AB: Determine which streams have an index relationship
|
// Walk until no dependent streams are left
|
||||||
// with the currently active rivers. This is needed so that
|
while (true)
|
||||||
// no merge is made between a new cross river and the
|
{
|
||||||
// currently active rivers. Where in the new cross river
|
// AB: Determine which streams have an index relationship
|
||||||
// a stream depends (index) on the active rivers.
|
// with the currently active rivers. This is needed so that
|
||||||
stream_array_t dependent_streams, free_streams;
|
// no merge is made between a new cross river and the
|
||||||
dependent_streams[0] = free_streams[0] = 0;
|
// currently active rivers. Where in the new cross river
|
||||||
find_index_relationship_streams(tdbb, opt, streams,
|
// a stream depends (index) on the active rivers.
|
||||||
dependent_streams, free_streams);
|
stream_array_t dependent_streams, free_streams;
|
||||||
|
dependent_streams[0] = free_streams[0] = 0;
|
||||||
|
find_index_relationship_streams(tdbb, opt, streams,
|
||||||
|
dependent_streams, free_streams);
|
||||||
|
|
||||||
// If we have dependent and free streams then we can't rely on
|
// If we have dependent and free streams then we can't rely on
|
||||||
// the sort node to be used for index navigation.
|
// the sort node to be used for index navigation.
|
||||||
if (dependent_streams[0] && free_streams[0]) {
|
if (dependent_streams[0] && free_streams[0]) {
|
||||||
sort = NULL;
|
sort = NULL;
|
||||||
sort_can_be_used = false;
|
sort_can_be_used = false;
|
||||||
}
|
|
||||||
|
|
||||||
if (dependent_streams[0]) {
|
|
||||||
// copy free streams
|
|
||||||
for (i = 0; i <= free_streams[0]; i++) {
|
|
||||||
streams[i] = free_streams[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make rivers from the dependent streams
|
if (dependent_streams[0]) {
|
||||||
gen_join(tdbb, opt, dependent_streams, rivers_stack, &sort,
|
// copy free streams
|
||||||
&project, rse->rse_plan);
|
for (i = 0; i <= free_streams[0]; i++) {
|
||||||
|
streams[i] = free_streams[i];
|
||||||
|
}
|
||||||
|
|
||||||
// Generate 1 river which holds a cross join rsb between
|
// Make rivers from the dependent streams
|
||||||
// all currently available rivers.
|
gen_join(tdbb, opt, dependent_streams, rivers_stack, &sort,
|
||||||
|
&project, rse->rse_plan);
|
||||||
|
|
||||||
// First get total count of streams.
|
// Generate 1 river which holds a cross join rsb between
|
||||||
int count = 0;
|
// all currently available rivers.
|
||||||
RiverStack::iterator stack1(rivers_stack);
|
|
||||||
for (; stack1.hasData(); ++stack1) {
|
// First get total count of streams.
|
||||||
count += stack1.object()->riv_count;
|
int count = 0;
|
||||||
|
RiverStack::iterator stack1(rivers_stack);
|
||||||
|
for (; stack1.hasData(); ++stack1) {
|
||||||
|
count += stack1.object()->riv_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create river and copy the streams.
|
||||||
|
River* river = FB_NEW_RPT(*tdbb->getDefaultPool(), count) River();
|
||||||
|
river->riv_count = (UCHAR) count;
|
||||||
|
UCHAR* stream_itr = river->riv_streams;
|
||||||
|
RiverStack::iterator stack2(rivers_stack);
|
||||||
|
for (; stack2.hasData(); ++stack2) {
|
||||||
|
River* subRiver = stack2.object();
|
||||||
|
MOVE_FAST(subRiver->riv_streams, stream_itr, subRiver->riv_count);
|
||||||
|
stream_itr += subRiver->riv_count;
|
||||||
|
}
|
||||||
|
river->riv_rsb = make_cross(tdbb, opt, rivers_stack);
|
||||||
|
rivers_stack.push(river);
|
||||||
|
|
||||||
|
// Mark the river as active.
|
||||||
|
set_made_river(opt, river);
|
||||||
|
set_active(opt, river);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (free_streams[0]) {
|
||||||
|
// Deactivate streams
|
||||||
|
for (i = 1; i <= sub_streams[0]; i++) {
|
||||||
|
csb->csb_rpt[sub_streams[i]].csb_flags &= ~csb_active;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create river and copy the streams.
|
break;
|
||||||
River* river = FB_NEW_RPT(*tdbb->getDefaultPool(), count) River();
|
|
||||||
river->riv_count = (UCHAR) count;
|
|
||||||
UCHAR* stream_itr = river->riv_streams;
|
|
||||||
RiverStack::iterator stack2(rivers_stack);
|
|
||||||
for (; stack2.hasData(); ++stack2) {
|
|
||||||
River* subRiver = stack2.object();
|
|
||||||
MOVE_FAST(subRiver->riv_streams, stream_itr, subRiver->riv_count);
|
|
||||||
stream_itr += subRiver->riv_count;
|
|
||||||
}
|
|
||||||
river->riv_rsb = make_cross(tdbb, opt, rivers_stack);
|
|
||||||
rivers_stack.push(river);
|
|
||||||
|
|
||||||
// Mark the river as active.
|
|
||||||
set_made_river(opt, river);
|
|
||||||
set_active(opt, river);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (free_streams[0]) {
|
|
||||||
// Deactivate streams
|
|
||||||
for (i = 1; i <= sub_streams[0]; i++) {
|
|
||||||
csb->csb_rpt[sub_streams[i]].csb_flags &= ~csb_active;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user