mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-24 00:03: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);
|
||||
|
||||
// AB: Determine which streams have an index relationship
|
||||
// with the currently active rivers. This is needed so that
|
||||
// no merge is made between a new cross river and the
|
||||
// currently active rivers. Where in the new cross river
|
||||
// a stream depends (index) on the active rivers.
|
||||
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);
|
||||
// Walk until no dependent streams are left
|
||||
while (true)
|
||||
{
|
||||
// AB: Determine which streams have an index relationship
|
||||
// with the currently active rivers. This is needed so that
|
||||
// no merge is made between a new cross river and the
|
||||
// currently active rivers. Where in the new cross river
|
||||
// a stream depends (index) on the active rivers.
|
||||
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
|
||||
// the sort node to be used for index navigation.
|
||||
if (dependent_streams[0] && free_streams[0]) {
|
||||
sort = NULL;
|
||||
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];
|
||||
// If we have dependent and free streams then we can't rely on
|
||||
// the sort node to be used for index navigation.
|
||||
if (dependent_streams[0] && free_streams[0]) {
|
||||
sort = NULL;
|
||||
sort_can_be_used = false;
|
||||
}
|
||||
|
||||
// Make rivers from the dependent streams
|
||||
gen_join(tdbb, opt, dependent_streams, rivers_stack, &sort,
|
||||
&project, rse->rse_plan);
|
||||
if (dependent_streams[0]) {
|
||||
// copy free streams
|
||||
for (i = 0; i <= free_streams[0]; i++) {
|
||||
streams[i] = free_streams[i];
|
||||
}
|
||||
|
||||
// Generate 1 river which holds a cross join rsb between
|
||||
// all currently available rivers.
|
||||
// Make rivers from the dependent streams
|
||||
gen_join(tdbb, opt, dependent_streams, rivers_stack, &sort,
|
||||
&project, rse->rse_plan);
|
||||
|
||||
// First get total count of streams.
|
||||
int count = 0;
|
||||
RiverStack::iterator stack1(rivers_stack);
|
||||
for (; stack1.hasData(); ++stack1) {
|
||||
count += stack1.object()->riv_count;
|
||||
// Generate 1 river which holds a cross join rsb between
|
||||
// all currently available rivers.
|
||||
|
||||
// First get total count of streams.
|
||||
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.
|
||||
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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user