Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unnest IN/ANY/EXISTS subqueries and optimize them using semi-join algorithm #8061

Draft
wants to merge 173 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
173 commits
Select commit Hold shift + click to select a range
ee56d5a
Added support for semi/anti and outer joins to hash join algorithm. R…
dyemanov Jul 3, 2023
9870b59
Handle not only possibly indexed booleans but all possible candidates…
dyemanov Jul 6, 2023
f561b80
Sync with master
dyemanov Mar 31, 2024
e6c5cda
increment build number
actions-user Mar 31, 2024
ca9f68f
Postfix for #7989 - Improve performance of external (UDR) functions (…
asfernandes Apr 1, 2024
c662fe4
Implementation of move semantics for Firebird::string (#8059)
Noremos Apr 1, 2024
48061c6
increment build number
actions-user Apr 1, 2024
4ec8045
Fix #8063 - (var)char variables/parameters assignments fail in Stored…
asfernandes Apr 2, 2024
ccaefed
PR #8059 postfix: Store temp test file in temp directory (#8065)
Noremos Apr 2, 2024
19dcc2b
Remove unused test file.
asfernandes Apr 2, 2024
f2181a9
increment build number
actions-user Apr 2, 2024
5667c9a
Fixed bug #7942 : Error: database file appears corrupted after restor…
hvlad Apr 2, 2024
3158ce4
Postfix for #7976: False validation error for short unpacked records …
dyemanov Apr 3, 2024
fa8b99d
increment build number
actions-user Apr 3, 2024
edaee40
Make fix for #8056 not break RDB$BLOB_UTIL with segmented blobs.
asfernandes Apr 3, 2024
ed43c60
Add missing synchronization to cached vectors of known pages (#8069)
dyemanov Apr 4, 2024
33b2366
increment build number
actions-user Apr 4, 2024
5d73d5a
Fix #8078 - `SIMILAR TO` with constant pattern using ‘|’, ‘*’, ‘?’ or…
asfernandes Apr 12, 2024
d15ce57
increment build number
actions-user Apr 12, 2024
c3f5d8b
Feature #8062 - CREATE IF NOT EXISTS. (#8072)
asfernandes Apr 14, 2024
a16502d
increment build number
actions-user Apr 14, 2024
bc1662b
Fixed FW=ON for the newly created database
dyemanov Apr 15, 2024
6ec264f
increment build number
actions-user Apr 15, 2024
04cc618
Postfix for #8062 - CREATE IF NOT EXISTS.
asfernandes Apr 16, 2024
2426957
Fixe bug #8083 : AV when writting into internal trace log
hvlad Apr 16, 2024
cee9f4a
Added assert to show bug #8079
hvlad Apr 11, 2024
85b81a6
Fixed bug #8079 : Engine could crash when executing some trigger(s) …
hvlad Apr 11, 2024
7ca6b43
Update docs
hvlad Apr 16, 2024
97095a4
increment build number
actions-user Apr 16, 2024
dc064e4
Fixed bug #8085 : Memory leak when executing a lot of different queri…
hvlad Apr 17, 2024
742b53e
Fixed bug #8084 : Partial index uniqueness violation
hvlad Apr 17, 2024
c3e9e6a
Fixed bug #8087 : AV when preparing a query with IN list that contain…
hvlad Apr 17, 2024
614a17f
increment build number
actions-user Apr 17, 2024
23d274d
Addition for bug #8084 : Partial index uniqueness violation.
hvlad Apr 18, 2024
1eb0c3d
increment build number
actions-user Apr 18, 2024
c84e436
Fixed memory statistics in debug build
AlexPeshkoff Apr 19, 2024
ae2c9e8
Fixed bug #8089 : AV when attaching database while low of free memory
hvlad Apr 19, 2024
289280a
increment build number
actions-user Apr 19, 2024
48c6645
Update deprecated GH action.
asfernandes Apr 22, 2024
05b46ee
increment build number
actions-user Apr 22, 2024
eb41819
Build cloop with -static-libstdc++.
asfernandes Apr 19, 2024
d9d135a
Update Linux build to use gcc 13.2 and binutils 2.40.
asfernandes Apr 19, 2024
8bee31f
Switch Linux docker build from ubuntu to debian.
asfernandes Apr 19, 2024
14436cd
Upgrade glibc to 2.28 and arm64 binutils to 2.40.
asfernandes Apr 19, 2024
8a83613
increment build number
actions-user Apr 23, 2024
3ebae71
Preliminary fix for #8077. Unfortunately if one turns on connections …
AlexPeshkoff Apr 24, 2024
9fd362b
Fixed #8034: set owner/group in tarball of non-root builds
AlexPeshkoff Apr 24, 2024
10a1f7f
Fixed #8037: remove directory entries from debug symbols tarball
AlexPeshkoff Apr 24, 2024
733e6db
increment build number
actions-user Apr 24, 2024
dc4f244
Fixed bug #8094 : Creation Index Error when restore with parallels wo…
hvlad Apr 26, 2024
e9f0c78
Implement #8066 : Make protocol schemes case-insensitive.
hvlad Apr 28, 2024
fc3d12c
increment build number
actions-user Apr 28, 2024
849bc0a
Implement #8010 : Remove gfix -cache option
hvlad Apr 28, 2024
071afad
Removed usage of deprecated items.
hvlad Apr 29, 2024
3eeea0d
increment build number
actions-user Apr 29, 2024
ae1565b
This should fix #8086: IN predicate with string-type elements is eval…
dyemanov May 1, 2024
d06cffd
Make bcb_flags atomic to avoid rare but still possible race condition
hvlad May 2, 2024
8e64708
increment build number
actions-user May 2, 2024
1b0d866
Improvement #8104 : Inefficient evaluation of expressions like rdb$db…
hvlad May 6, 2024
e791e34
increment build number
actions-user May 6, 2024
76348cc
Fix #8100 - The isc_array_lookup_bounds function returns invalid valu…
asfernandes May 5, 2024
a813204
increment build number
actions-user May 7, 2024
42fc5f6
Added missing privilege to doc
AlexPeshkoff May 8, 2024
3e80109
Merge pull request #8106 from FirebirdSQL/work/gh-8105
hvlad May 8, 2024
21c530b
increment build number
actions-user May 8, 2024
cbfdf38
This should fix bug #8114 : Segfault in connections pool during serve…
hvlad May 14, 2024
b0c77dc
Fix for #8101
aafemt May 5, 2024
120fad6
increment build number
actions-user May 14, 2024
0f4cd5d
Fix #8112 - Error isc_read_only_trans (335544361) should report SQLST…
asfernandes May 15, 2024
ecaed60
Fixed bug #8110 : Firebird 5 crash On Android API level 34
hvlad May 14, 2024
d6add8a
Fix for issue #8108 [frontported from FB4] (#8118)
dmitry-lipetsk May 15, 2024
9eb4a55
increment build number
actions-user May 15, 2024
4e8f456
Fix debug build failure with assertion in CRT (#8121)
aafemt May 16, 2024
b5502d3
increment build number
actions-user May 16, 2024
76661a3
Try avoiding new git security measure
asfernandes May 17, 2024
5e0d0a8
increment build number
actions-user May 17, 2024
2fd3f65
Fiz tzdata-update workflow.
asfernandes May 18, 2024
cb9a8b8
increment build number
actions-user May 18, 2024
f0ecaa3
Fix #8123 - Procedure manipulation can lead to wrong dependencies rem…
asfernandes May 21, 2024
a8ff586
increment build number
actions-user May 21, 2024
932ae5f
Fix for #8077: Error "Too many recursion levels" does not stop execui…
AlexPeshkoff May 23, 2024
2195466
increment build number
actions-user May 23, 2024
125f82c
Fixed possible buffer overflow on system privileges lookup during use…
dmitry-starodubov May 24, 2024
250b1a1
Simplest fix for bug #8120 : Cast dies with numeric value is out of r…
hvlad May 24, 2024
af848a4
increment build number
actions-user May 24, 2024
eb935c3
Correction for #8069.
hvlad May 27, 2024
e90d39e
increment build number
actions-user May 27, 2024
c12fbbb
Misc
dyemanov May 28, 2024
de77269
Fixed #8136: Server crashes with IN (dbkey1, dbkey2, ...) condition
dyemanov May 28, 2024
9a067f6
Attempt to avoid hash joining for possible cardinality under-estimations
dyemanov May 28, 2024
78171f3
increment build number
actions-user May 28, 2024
9c26932
Restored correct permissions
AlexPeshkoff May 30, 2024
2f790fb
increment build number
actions-user May 30, 2024
29b6c36
Refactoring of CAST FORMAT (#7881) (#8134)
TreeHunter9 Jun 3, 2024
48ab192
increment build number
actions-user Jun 3, 2024
f440e38
Fixed bug #8149 : The hung or crash could happen when connection fire…
hvlad Jun 5, 2024
1361344
Fixed bug #8150 : Process could attach to the deleted instance of sha…
hvlad Jun 5, 2024
0fba698
Fixed bug #8151 : Deadlock happens when run 'List Trace Sessions' ser…
hvlad Jun 5, 2024
1e96dad
increment build number
actions-user Jun 5, 2024
1e51ddb
Undone part of recent fix for #8151 as it prevents trace session from…
hvlad Jun 8, 2024
a49f4e9
increment build number
actions-user Jun 8, 2024
6d505d2
This should fix bug #8138 : Bugcheck when replicator state is changed…
hvlad May 28, 2024
7fa19d8
increment build number
actions-user Jun 9, 2024
2d6f2e6
Fixed bug #8156 : Can not specify concrete IPv6 address in ES/EDS con…
hvlad Jun 13, 2024
5fa88a2
increment build number
actions-user Jun 13, 2024
3cd631e
Use @ consistently to produce cleaner output
reevespaul Jun 21, 2024
941ff8a
White space; spelling; misc
reevespaul Jun 21, 2024
7738836
cleanup
reevespaul Jun 21, 2024
087f744
Remove obsolete debug code
reevespaul Jun 21, 2024
3311cfb
Add option to package without release notes
reevespaul Jun 21, 2024
65c07a5
Dynamically set FB_MAJOR_VER
reevespaul Jun 21, 2024
55d3fb2
Improve installed product detection (WIP)
reevespaul Jun 21, 2024
10c8c0d
Improve detection of existing configured security database
reevespaul Jun 21, 2024
b146425
Replace tabs with spaces
reevespaul Jun 21, 2024
2993ed6
Fix #7911 - allow spaces in service name
reevespaul Jun 21, 2024
b33c52d
increment build number
actions-user Jun 21, 2024
64206b4
Feature #7980 - Option for GEN_UUID to generate v7 UUID.
asfernandes Jun 22, 2024
4e5ffa7
Refactor GEN_UUID for v4.
asfernandes Jun 22, 2024
4202e21
increment build number
actions-user Jun 23, 2024
afdde9a
Merge pull request #8169 from FirebirdSQL/work/gh-8168
hvlad Jun 27, 2024
3b7f8f7
increment build number
actions-user Jun 27, 2024
0dc7354
Frontported bugfix for blob access vs replicator
dyemanov Jun 30, 2024
eb90a37
increment build number
actions-user Jun 30, 2024
695d8f4
Avoid not necessary allocations from pool when performing FK check.
hvlad Jul 5, 2024
b1ff96c
increment build number
actions-user Jul 5, 2024
7ccd1ea
Fixed bug #8171 : Trace plugin unloaded if called method is not imple…
hvlad Jul 7, 2024
9dc1949
Added shutdown handler for server (#8165)
Zhdanov0 Jul 8, 2024
457bde3
increment build number
actions-user Jul 8, 2024
c58597e
Fix #8172 - The file include/firebird/impl/iberror_c.h is missing in …
asfernandes Jul 9, 2024
497319f
increment build number
actions-user Jul 9, 2024
a33472d
Do not delete system trace session with missing parent process (fix f…
Noremos Jul 10, 2024
2e15651
Fix boolean conversion to string inside DataTypeUtil::makeFromList() …
dyemanov Jul 10, 2024
7aaf504
Fixed bug #8176 : Firebird 5 hang after starting remote profiling ses…
hvlad Jul 9, 2024
18d3083
increment build number
actions-user Jul 10, 2024
026451b
Ensure the CS listener uses the SO_REUSEADDR socket option (#8181)
dyemanov Jul 13, 2024
137f560
increment build number
actions-user Jul 13, 2024
3d12d80
Fixed bug #8189 : Slow connection times with a lot of simultaneous co…
hvlad Jul 22, 2024
a741cbe
increment build number
actions-user Jul 22, 2024
fd2aa44
A bit better patch for #8189 : Slow connection times with a lot of si…
hvlad Jul 23, 2024
c4d9620
increment build number
actions-user Jul 23, 2024
f321819
Frontported PR #8186 : Fixed a few issues with IPC used by remote pro…
hvlad Jul 24, 2024
913cfed
Additinal fix for #8180: Make sure trace session slots will not break…
Noremos Jul 24, 2024
b1e4e5c
increment build number
actions-user Jul 24, 2024
fda662e
Minor static analysis fixes (#8195)
marat-iskakov Jul 26, 2024
fe6f1ac
increment build number
actions-user Jul 26, 2024
5ab64aa
Fix #8185 - SIGSEGV with WHERE CURRENT OF statement with statement ca…
asfernandes Jul 23, 2024
df8d12f
Front port misc changes to installer packaging from FB5
reevespaul Jul 29, 2024
f15faf1
increment build number
actions-user Jul 29, 2024
075d0e6
This should fix bug #8194 : Internal consistency check (page in use d…
hvlad Jul 30, 2024
a59284d
Correction as suggested by Dimitry Sibiryakov
dyemanov Jul 31, 2024
c1ddb27
increment build number
actions-user Jul 31, 2024
2748605
Fix #8187 - Performance regression in generating of UUID values after…
asfernandes Aug 1, 2024
f9fd4b9
increment build number
actions-user Aug 1, 2024
defb6ad
Do not fail packaging if implib not found
reevespaul Aug 2, 2024
501e2ec
Delete temporary secdb init files immediately (with thanks to Vlad)
reevespaul Aug 2, 2024
99af2c8
Add script to test binary installer options
reevespaul Aug 2, 2024
1b5234c
increment build number
actions-user Aug 2, 2024
5964265
Regenerate system triggers improving formatting and constant names.
asfernandes Aug 2, 2024
234fc28
Add CachedRequestId mechanism for internal request cache.
asfernandes Aug 2, 2024
ccfd764
Reimplement system triggers in C++/GDML code.
asfernandes Aug 2, 2024
0d6d40a
Preprocess SystemTriggers in windows build boot phase.
asfernandes Aug 2, 2024
dd6c298
Replace individual public functions by moment/type execute categories.
asfernandes Aug 2, 2024
6322727
Correction for drop not null constraint validation.
asfernandes Aug 3, 2024
b515056
Correction: disallow updates in RDB$USER_PRIVILEGES.
asfernandes Aug 3, 2024
9f57789
Correction: revert code related with WITH CHECK OPTION internal trigg…
asfernandes Aug 4, 2024
1508f11
Misc.
asfernandes Aug 5, 2024
2e094f7
increment build number
actions-user Aug 5, 2024
d670ad6
Correction for #8202.
asfernandes Aug 6, 2024
6627097
Add manual delete for tra_dbcreators_list (#8207)
TreeHunter9 Aug 6, 2024
ed6669f
increment build number
actions-user Aug 6, 2024
c888168
Merge pull request #8204 from FirebirdSQL/work/gh-8203
hvlad Aug 5, 2024
e67f85e
Sync with v5
dyemanov Nov 16, 2024
3edc9c5
Merge branch 'master' into semi-joins
dyemanov Nov 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
259 changes: 255 additions & 4 deletions src/jrd/RecordSourceNodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,167 @@ static void genDeliverUnmapped(CompilerScratch* csb, const BoolExprNodeStack& pa
static ValueExprNode* resolveUsingField(DsqlCompilerScratch* dsqlScratch, const MetaName& name,
ValueListNode* list, const FieldNode* flawedNode, const TEXT* side, dsql_ctx*& ctx);

namespace
{
// Search through the list of ANDed booleans to find comparisons
// referring streams of parent select expressions.
// Extract those booleans and return them to the caller.

bool findDependentBooleans(CompilerScratch* csb,
const StreamList& rseStreams,
BoolExprNode** parentBoolean,
BoolExprNodeStack& booleanStack)
{
const auto boolean = *parentBoolean;

const auto binaryNode = nodeAs<BinaryBoolNode>(boolean);
if (binaryNode && binaryNode->blrOp == blr_and)
{
const bool found1 = findDependentBooleans(csb, rseStreams,
binaryNode->arg1.getAddress(), booleanStack);
const bool found2 = findDependentBooleans(csb, rseStreams,
binaryNode->arg2.getAddress(), booleanStack);

if (!binaryNode->arg1 && !binaryNode->arg2)
*parentBoolean = nullptr;
else if (!binaryNode->arg1)
*parentBoolean = binaryNode->arg2;
else if (!binaryNode->arg2)
*parentBoolean = binaryNode->arg1;

return (found1 || found2);
}

if (const auto cmpNode = nodeAs<ComparativeBoolNode>(boolean))
{
if (cmpNode->blrOp == blr_eql || cmpNode->blrOp == blr_equiv)
{
SortedStreamList streams;
cmpNode->collectStreams(streams);

for (const auto stream : streams)
{
if (rseStreams.exist(stream))
{
booleanStack.push(boolean);
*parentBoolean = nullptr;
return true;
}
}
}
}

return false;
}

// Search through the list of ANDed booleans to find correlated EXISTS/IN sub-queries.
// They are candidates to be converted into semi- or anti-joins.

bool findPossibleJoins(CompilerScratch* csb,
const StreamList& rseStreams,
BoolExprNode** parentBoolean,
RecordSourceNodeStack& rseStack,
BoolExprNodeStack& booleanStack)
{
auto boolNode = *parentBoolean;

const auto binaryNode = nodeAs<BinaryBoolNode>(boolNode);
if (binaryNode && binaryNode->blrOp == blr_and)
{
const bool found1 = findPossibleJoins(csb, rseStreams,
binaryNode->arg1.getAddress(), rseStack, booleanStack);
const bool found2 = findPossibleJoins(csb, rseStreams,
binaryNode->arg2.getAddress(), rseStack, booleanStack);

if (!binaryNode->arg1 && !binaryNode->arg2)
*parentBoolean = nullptr;
else if (!binaryNode->arg1)
*parentBoolean = binaryNode->arg2;
else if (!binaryNode->arg2)
*parentBoolean = binaryNode->arg1;

return (found1 || found2);
}

const auto rseNode = nodeAs<RseBoolNode>(boolNode);
// Both EXISTS (blr_any) and IN (blr_ansi_any) sub-queries are handled
if (rseNode && (rseNode->blrOp == blr_any || rseNode->blrOp == blr_ansi_any))
{
auto rse = rseNode->rse;
fb_assert(rse && (rse->flags & RseNode::FLAG_SUB_QUERY));

if (rse->rse_boolean && rse->rse_jointype == blr_inner &&
!rse->rse_first && !rse->rse_skip && !rse->rse_plan)
{
// Find booleans convertable into semi-joins

StreamList streams;
rse->computeRseStreams(streams);

BoolExprNodeStack booleans;
if (findDependentBooleans(csb, rseStreams,
rse->rse_boolean.getAddress(),
booleans))
{
// Compose the conjunct boolean

fb_assert(booleans.hasData());
auto boolean = booleans.pop();
while (booleans.hasData())
{
const auto andNode = FB_NEW_POOL(csb->csb_pool)
BinaryBoolNode(csb->csb_pool, blr_and);
andNode->arg1 = boolean;
andNode->arg2 = booleans.pop();
boolean = andNode;
}

// Ensure that no external references are left inside the subquery.
// If so, mark the RSE as joined and add it to the stack.

SortedStreamList streams;
rse->collectStreams(streams);

bool dependent = false;
for (const auto stream : streams)
{
if (rseStreams.exist(stream))
{
dependent = true;
break;
}
}

if (!dependent)
{
rse->flags &= ~RseNode::FLAG_SUB_QUERY;
rse->flags |= RseNode::FLAG_SEMI_JOINED;
rseStack.push(rse);
booleanStack.push(boolean);
*parentBoolean = nullptr;
return true;
}

// Otherwise, restore the original sub-query by adding
// the collected booleans back to the RSE.

if (rse->rse_boolean)
{
const auto andNode = FB_NEW_POOL(csb->csb_pool)
BinaryBoolNode(csb->csb_pool, blr_and);
andNode->arg1 = boolean;
andNode->arg2 = rse->rse_boolean;
boolean = andNode;
}

rse->rse_boolean = boolean;
}
}
}

return false;
}
}

//--------------------

Expand Down Expand Up @@ -2992,6 +3153,9 @@ RseNode* RseNode::pass1(thread_db* tdbb, CompilerScratch* csb)
{
SET_TDBB(tdbb);

if (const auto newRse = processPossibleJoins(tdbb, csb))
return newRse->pass1(tdbb, csb);

// for scoping purposes, maintain a stack of RseNode's which are
// currently being parsed; if there are none on the stack as
// yet, mark the RseNode as variant to make sure that statement-
Expand Down Expand Up @@ -3097,6 +3261,12 @@ RseNode* RseNode::pass1(thread_db* tdbb, CompilerScratch* csb)
void RseNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* rse,
BoolExprNode** boolean, RecordSourceNodeStack& stack)
{
if (const auto newRse = processPossibleJoins(tdbb, csb))
{
newRse->pass1Source(tdbb, csb, rse, boolean, stack);
return;
}

if (rse_jointype != blr_inner)
{
// Check whether any of the upper level booleans (those belonging to the WHERE clause)
Expand Down Expand Up @@ -3150,15 +3320,15 @@ void RseNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* rse,
}
}

// in the case of an RseNode, it is possible that a new RseNode will be generated,
// In the case of an RseNode, it is possible that a new RseNode will be generated,
// so wait to process the source before we push it on the stack (bug 8039)

// The addition of the JOIN syntax for specifying inner joins causes an
// RseNode tree to be generated, which is undesirable in the simplest case
// where we are just trying to inner join more than 2 streams. If possible,
// try to flatten the tree out before we go any further.

if (!isLateral() &&
if (!isLateral() && !isSemiJoined() &&
rse->rse_jointype == blr_inner &&
rse_jointype == blr_inner &&
!rse_sorted && !rse_projection &&
Expand Down Expand Up @@ -3263,11 +3433,11 @@ RecordSource* RseNode::compile(thread_db* tdbb, Optimizer* opt, bool innerSubStr

StreamStateHolder stateHolder(csb, opt->getOuterStreams());

if (opt->isLeftJoin() || isLateral())
if (opt->isLeftJoin() || isLateral() || isSemiJoined())
{
stateHolder.activate();

if (opt->isLeftJoin())
if (opt->isLeftJoin() || isSemiJoined())
{
// Push all conjuncts except "missing" ones (e.g. IS NULL)
for (auto iter = opt->getConjuncts(false, true); iter.hasData(); ++iter)
Expand All @@ -3290,6 +3460,87 @@ RecordSource* RseNode::compile(thread_db* tdbb, Optimizer* opt, bool innerSubStr
return opt->compile(this, &conjunctStack);
}

RseNode* RseNode::processPossibleJoins(thread_db* tdbb, CompilerScratch* csb)
{
if (rse_jointype != blr_inner || !rse_boolean || rse_plan)
return nullptr;

// If the sub-query is nested inside the other sub-query which wasn't converted into semi-join,
// it makes no sense to apply a semi-join at the deeper levels, as a sub-query is expected
// to be executed repeatedly.
// This is a temporary fix until nested loop semi-joins are allowed by the optimizer.

if (flags & FLAG_SUB_QUERY)
return nullptr;

for (const auto node : csb->csb_current_nodes)
{
if (const auto rse = nodeAs<RseNode>(node))
{
if (rse->flags & FLAG_SUB_QUERY)
return nullptr;
}
}

RecordSourceNodeStack rseStack;
BoolExprNodeStack booleanStack;

// Find possibly joinable sub-queries

StreamList rseStreams;
computeRseStreams(rseStreams);

if (!findPossibleJoins(csb, rseStreams, rse_boolean.getAddress(), rseStack, booleanStack))
return nullptr;

fb_assert(rseStack.hasData() && booleanStack.hasData());
fb_assert(rseStack.getCount() == booleanStack.getCount());

// Create joins between the original node and detected joinable nodes.
// Preserve FIRST/SKIP nodes at their original position, i.e. outside semi-joins.

const auto first = rse_first;
rse_first = nullptr;

const auto skip = rse_skip;
rse_skip = nullptr;

const auto orgFlags = flags;
flags = 0;

auto rse = this;
while (rseStack.hasData())
{
const auto newRse = FB_NEW_POOL(*tdbb->getDefaultPool())
RseNode(*tdbb->getDefaultPool());

newRse->rse_relations.add(rse);
newRse->rse_relations.add(rseStack.pop());

newRse->rse_jointype = blr_inner;
newRse->rse_boolean = booleanStack.pop();

rse = newRse;
}

if (first || skip)
{
const auto newRse = FB_NEW_POOL(*tdbb->getDefaultPool())
RseNode(*tdbb->getDefaultPool());

newRse->rse_relations.add(rse);
newRse->rse_jointype = blr_inner;
newRse->rse_first = first;
newRse->rse_skip = skip;

rse = newRse;
}

rse->flags = orgFlags;

return rse;
}

// Check that all streams in the RseNode have a plan specified for them.
// If they are not, there are streams in the RseNode which were not mentioned in the plan.
void RseNode::planCheck(const CompilerScratch* csb) const
Expand Down
23 changes: 15 additions & 8 deletions src/jrd/RecordSourceNodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -718,14 +718,15 @@ class RseNode final : public TypedNode<RecordSourceNode, RecordSourceNode::TYPE_
public:
enum : USHORT
{
FLAG_VARIANT = 0x01, // variant (not invariant?)
FLAG_SINGULAR = 0x02, // singleton select
FLAG_WRITELOCK = 0x04, // locked for write
FLAG_SCROLLABLE = 0x08, // scrollable cursor
FLAG_DSQL_COMPARATIVE = 0x10, // transformed from DSQL ComparativeBoolNode
FLAG_LATERAL = 0x20, // lateral derived table
FLAG_SKIP_LOCKED = 0x40, // skip locked
FLAG_SUB_QUERY = 0x80 // sub-query
FLAG_VARIANT = 0x01, // variant (not invariant?)
FLAG_SINGULAR = 0x02, // singleton select
FLAG_WRITELOCK = 0x04, // locked for write
FLAG_SCROLLABLE = 0x08, // scrollable cursor
FLAG_DSQL_COMPARATIVE = 0x10, // transformed from DSQL ComparativeBoolNode
FLAG_LATERAL = 0x20, // lateral derived table
FLAG_SKIP_LOCKED = 0x40, // skip locked
FLAG_SUB_QUERY = 0x80, // sub-query
FLAG_SEMI_JOINED = 0x100 // participates in semi-join
};

bool isInvariant() const
Expand Down Expand Up @@ -753,6 +754,11 @@ class RseNode final : public TypedNode<RecordSourceNode, RecordSourceNode::TYPE_
return (flags & FLAG_SUB_QUERY) != 0;
}

bool isSemiJoined() const
{
return (flags & FLAG_SEMI_JOINED) != 0;
}

bool hasWriteLock() const
{
return (flags & FLAG_WRITELOCK) != 0;
Expand Down Expand Up @@ -857,6 +863,7 @@ class RseNode final : public TypedNode<RecordSourceNode, RecordSourceNode::TYPE_
private:
void planCheck(const CompilerScratch* csb) const;
static void planSet(CompilerScratch* csb, PlanNode* plan);
RseNode* processPossibleJoins(thread_db* tdbb, CompilerScratch* csb);

public:
NestConst<ValueExprNode> dsqlFirst;
Expand Down
2 changes: 1 addition & 1 deletion src/jrd/SysFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6969,7 +6969,7 @@ const SysFunction SysFunction::functions[] =
{"UNICODE_CHAR", 1, 1, true, setParamsInteger, makeUnicodeChar, evlUnicodeChar, NULL},
{"UNICODE_VAL", 1, 1, true, setParamsUnicodeVal, makeLongResult, evlUnicodeVal, NULL},
{"UUID_TO_CHAR", 1, 1, true, setParamsUuidToChar, makeUuidToChar, evlUuidToChar, NULL},
{"", 0, 0, NULL, NULL, NULL, NULL}
{"", 0, 0, false, NULL, NULL, NULL, NULL}
};


Expand Down
Loading
Loading