mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 21:23:04 +01:00
Backport bugfix for #7937: Inner join raises error 'no current record for fetch operation' if a stored procedure depends on some table via input parameter and also has an indexed relationship with another table
This commit is contained in:
parent
ad0e5ce0a9
commit
b4b355978f
@ -174,6 +174,7 @@ namespace
|
||||
// Save states of the underlying streams and restore them afterwards
|
||||
|
||||
StreamStateHolder stateHolder(csb, m_streams);
|
||||
stateHolder.deactivate();
|
||||
|
||||
// Generate record source objects
|
||||
|
||||
@ -569,7 +570,6 @@ Optimizer::Optimizer(thread_db* aTdbb, CompilerScratch* aCsb, RseNode* aRse, boo
|
||||
compileStreams(getPool()),
|
||||
bedStreams(getPool()),
|
||||
keyStreams(getPool()),
|
||||
subStreams(getPool()),
|
||||
outerStreams(getPool()),
|
||||
conjuncts(getPool())
|
||||
{
|
||||
@ -814,7 +814,7 @@ RecordSource* Optimizer::compile(BoolExprNodeStack* parentStack)
|
||||
// Go through the record selection expression generating
|
||||
// record source blocks for all streams
|
||||
|
||||
RiverList rivers;
|
||||
RiverList rivers, dependentRivers;
|
||||
|
||||
bool innerSubStream = false;
|
||||
for (auto node : rse->rse_relations)
|
||||
@ -840,11 +840,13 @@ RecordSource* Optimizer::compile(BoolExprNodeStack* parentStack)
|
||||
StreamList localStreams;
|
||||
rsb->findUsedStreams(localStreams);
|
||||
|
||||
bool computable = false;
|
||||
|
||||
// AB: Save all outer-part streams
|
||||
if (isInnerJoin() || (isLeftJoin() && !innerSubStream))
|
||||
{
|
||||
subStreams.join(localStreams);
|
||||
outerStreams.join(localStreams);
|
||||
if (node->computable(csb, INVALID_STREAM, false))
|
||||
computable = true;
|
||||
|
||||
// Apply local booleans, if any. Note that it's done
|
||||
// only for inner joins and outer streams of left joins.
|
||||
@ -854,9 +856,18 @@ RecordSource* Optimizer::compile(BoolExprNodeStack* parentStack)
|
||||
|
||||
const auto river = FB_NEW_POOL(getPool()) River(csb, rsb, node, localStreams);
|
||||
river->deactivate(csb);
|
||||
|
||||
if (computable)
|
||||
{
|
||||
outerStreams.join(localStreams);
|
||||
rivers.add(river);
|
||||
}
|
||||
else
|
||||
{
|
||||
dependentRivers.add(river);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We have a relation, just add its stream
|
||||
fb_assert(bedStreams.hasData());
|
||||
@ -883,9 +894,9 @@ RecordSource* Optimizer::compile(BoolExprNodeStack* parentStack)
|
||||
else
|
||||
rse->rse_aggregate = aggregate = nullptr;
|
||||
|
||||
// AB: Mark the previous used streams (sub-RseNode's) as active
|
||||
for (const auto subStream : subStreams)
|
||||
csb->csb_rpt[subStream].activate();
|
||||
// Activate the priorly used rivers
|
||||
for (const auto river : rivers)
|
||||
river->activate(csb);
|
||||
|
||||
bool sortCanBeUsed = true;
|
||||
SortNode* const orgSortNode = sort;
|
||||
@ -904,7 +915,10 @@ RecordSource* Optimizer::compile(BoolExprNodeStack* parentStack)
|
||||
|
||||
// Outer joins are processed their own way
|
||||
if (!isInnerJoin())
|
||||
{
|
||||
rivers.join(dependentRivers);
|
||||
rsb = generateOuterJoin(rivers, &sort);
|
||||
}
|
||||
else
|
||||
{
|
||||
// AB: If previous rsb's are already on the stack we can't use
|
||||
@ -971,13 +985,18 @@ RecordSource* Optimizer::compile(BoolExprNodeStack* parentStack)
|
||||
}
|
||||
}
|
||||
|
||||
// attempt to form joins in decreasing order of desirability
|
||||
// Attempt to form joins in decreasing order of desirability
|
||||
generateInnerJoin(joinStreams, rivers, &sort, rse->rse_plan);
|
||||
|
||||
// Re-activate remaining rivers to be hashable/mergeable
|
||||
for (const auto river : rivers)
|
||||
river->activate(csb);
|
||||
|
||||
// If there are multiple rivers, try some hashing or sort/merging
|
||||
while (generateEquiJoin(rivers))
|
||||
;
|
||||
|
||||
rivers.join(dependentRivers);
|
||||
rsb = CrossJoin(csb, rivers).getRecordSource();
|
||||
|
||||
// Pick up any residual boolean that may have fallen thru the cracks
|
||||
@ -2263,6 +2282,9 @@ bool Optimizer::generateEquiJoin(RiverList& orgRivers)
|
||||
if (iter & CONJUNCT_USED)
|
||||
continue;
|
||||
|
||||
if (!iter->computable(csb, INVALID_STREAM, false))
|
||||
continue;
|
||||
|
||||
NestConst<ValueExprNode> node1;
|
||||
NestConst<ValueExprNode> node2;
|
||||
|
||||
|
@ -548,7 +548,7 @@ private:
|
||||
unsigned baseParentConjuncts = 0; // number of conjuncts in our rse + distributed with parent, next are parent
|
||||
unsigned baseMissingConjuncts = 0; // number of conjuncts in our and parent rse, but without missing
|
||||
|
||||
StreamList compileStreams, bedStreams, keyStreams, subStreams, outerStreams;
|
||||
StreamList compileStreams, bedStreams, keyStreams, outerStreams;
|
||||
ConjunctList conjuncts;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user