Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion src/jrd/Statement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "../jrd/scl_proto.h"
#include "../jrd/Collation.h"
#include "../jrd/recsrc/Cursor.h"
#include "../jrd/optimizer/Optimizer.h"

using namespace Firebird;
using namespace Jrd;
Expand Down Expand Up @@ -351,7 +352,7 @@ Statement* Statement::makeBoolExpression(thread_db* tdbb, BoolExprNode*& node,
return makeStatement(tdbb, csb, internalFlag,
[&]
{
node = static_cast<BoolExprNode*>(csb->csb_node);
node = Optimizer::transformBoolean(tdbb, csb);
});
}

Expand Down
82 changes: 74 additions & 8 deletions src/jrd/optimizer/Optimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,17 @@ Optimizer::Optimizer(thread_db* aTdbb, CompilerScratch* aCsb, RseNode* aRse,
}


Optimizer::Optimizer(thread_db* aTdbb, CompilerScratch* aCsb)
: PermanentStorage(*aTdbb->getDefaultPool()),
tdbb(aTdbb), csb(aCsb), rse(nullptr),
compileStreams(getPool()),
bedStreams(getPool()),
keyStreams(getPool()),
outerStreams(getPool()),
conjuncts(getPool())
{
}

//
// Destructor
//
Expand Down Expand Up @@ -1274,24 +1285,26 @@ void Optimizer::compileRelation(StreamType stream)


//
// Decompose a boolean into a stack of conjuctions.
// Decompose a boolean into a stack of conjunctions.
//
// If the boolean already transformed, don't transform it again.
//

unsigned Optimizer::decomposeBoolean(BoolExprNode* boolNode, BoolExprNodeStack& stack)
unsigned Optimizer::decomposeBoolean(BoolExprNode* boolNode, BoolExprNodeStack& stack, bool transformed)
{
if (const auto binaryNode = nodeAs<BinaryBoolNode>(boolNode))
{
if (binaryNode->blrOp == blr_and)
{
auto count = decomposeBoolean(binaryNode->arg1, stack);
count += decomposeBoolean(binaryNode->arg2, stack);
auto count = decomposeBoolean(binaryNode->arg1, stack, transformed);
count += decomposeBoolean(binaryNode->arg2, stack, transformed);
return count;
}
else if (binaryNode->blrOp == blr_or)
else if ((binaryNode->blrOp == blr_or) && !transformed)
{
BoolExprNodeStack or_stack;

if (decomposeBoolean(binaryNode->arg1, or_stack) >= 2)
if (decomposeBoolean(binaryNode->arg1, or_stack, transformed) >= 2)
{
binaryNode->arg1 = or_stack.pop();

Expand All @@ -1308,7 +1321,7 @@ unsigned Optimizer::decomposeBoolean(BoolExprNode* boolNode, BoolExprNodeStack&

or_stack.clear();

if (decomposeBoolean(binaryNode->arg2, or_stack) >= 2)
if (decomposeBoolean(binaryNode->arg2, or_stack, transformed) >= 2)
{
binaryNode->arg2 = or_stack.pop();

Expand All @@ -1330,6 +1343,8 @@ unsigned Optimizer::decomposeBoolean(BoolExprNode* boolNode, BoolExprNodeStack&

if (cmpNode->blrOp == blr_between)
{
fb_assert(!transformed);

auto newCmpNode = FB_NEW_POOL(getPool()) ComparativeBoolNode(getPool(), blr_geq);
newCmpNode->arg1 = cmpNode->arg1;
newCmpNode->arg2 = cmpNode->arg2;
Expand All @@ -1350,7 +1365,7 @@ unsigned Optimizer::decomposeBoolean(BoolExprNode* boolNode, BoolExprNodeStack&

ValueExprNode* arg;

if ((cmpNode->blrOp == blr_like || cmpNode->blrOp == blr_similar) &&
if ((cmpNode->blrOp == blr_like || cmpNode->blrOp == blr_similar) && !transformed &&
(arg = optimizeLikeSimilar(cmpNode)))
{
const auto newCmpNode =
Expand All @@ -1371,6 +1386,57 @@ unsigned Optimizer::decomposeBoolean(BoolExprNode* boolNode, BoolExprNodeStack&
}


//
// Transform boolean expression into form better suitable for later matching against
// another expression being optimized. Used with conditional indices.
//

BoolExprNode* Optimizer::transformBoolean(thread_db* tdbb, CompilerScratch* csb)
{
fb_assert(csb->csb_node->getKind() == DmlNode::KIND_BOOLEAN);

auto* node = static_cast<BoolExprNode*>(csb->csb_node);

Optimizer opt(tdbb, csb);
node = opt.transformBoolExpr(tdbb, node);
csb->csb_node = node;
return node;
}


BoolExprNode* Optimizer::transformBoolExpr(thread_db* tdbb, BoolExprNode* boolNode)
{
if (const auto binaryNode = nodeAs<BinaryBoolNode>(boolNode))
{
binaryNode->arg1 = transformBoolExpr(tdbb, binaryNode->arg1);
binaryNode->arg2 = transformBoolExpr(tdbb, binaryNode->arg2);
return binaryNode;
}

if (const auto cmpNode = nodeAs<ComparativeBoolNode>(boolNode))
{
// turn a between into (a greater than or equal) AND (a less than or equal)

if (cmpNode->blrOp == blr_between)
{
MemoryPool& pool = getPool();

auto geq = FB_NEW_POOL(pool) ComparativeBoolNode(pool, blr_geq);
geq->arg1 = cmpNode->arg1;
geq->arg2 = cmpNode->arg2;

auto leq = FB_NEW_POOL(pool) ComparativeBoolNode(pool, blr_leq);
leq->arg1 = CMP_clone_node_opt(tdbb, csb, cmpNode->arg1);
leq->arg2 = cmpNode->arg3;

return FB_NEW_POOL(pool) BinaryBoolNode(pool, blr_and, geq, leq);
}
}

return boolNode;
}


//
// Generate a separate AggregateSort (Aggregate SortedStream Block) for each distinct operation.
// Note that this should be optimized to use indices if possible.
Expand Down
7 changes: 6 additions & 1 deletion src/jrd/optimizer/Optimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,10 @@ class Optimizer : public Firebird::PermanentStorage

RecordSource* compile(RseNode* subRse, BoolExprNodeStack* parentStack);
void compileRelation(StreamType stream);
unsigned decomposeBoolean(BoolExprNode* boolNode, BoolExprNodeStack& stack);
unsigned decomposeBoolean(BoolExprNode* boolNode, BoolExprNodeStack& stack, bool transformed = false);

static BoolExprNode* transformBoolean(thread_db* tdbb, CompilerScratch* csb);

void generateAggregateDistincts(MapNode* map);
RecordSource* generateRetrieval(StreamType stream,
SortNode** sortClause,
Expand Down Expand Up @@ -569,6 +572,7 @@ class Optimizer : public Firebird::PermanentStorage
private:
Optimizer(thread_db* aTdbb, CompilerScratch* aCsb, RseNode* aRse, bool parentFirstRows);
Optimizer(thread_db* aTdbb, CompilerScratch* aCsb, RseNode* aRse, const BoolExprNodeStack& stack);
Optimizer(thread_db* aTdbb, CompilerScratch* aCsb);

RecordSource* compile(BoolExprNodeStack* parentStack);

Expand Down Expand Up @@ -603,6 +607,7 @@ class Optimizer : public Firebird::PermanentStorage
ValueListNode* list);

ValueExprNode* optimizeLikeSimilar(ComparativeBoolNode* cmpNode);
BoolExprNode* transformBoolExpr(thread_db* tdbb, BoolExprNode* boolNode);

thread_db* const tdbb;
CompilerScratch* const csb;
Expand Down
2 changes: 1 addition & 1 deletion src/jrd/optimizer/Retrieval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,7 @@ bool Retrieval::checkIndexCondition(index_desc& idx, MatchedBooleanList& matches
auto iter = optimizer->getConjuncts(outerFlag, innerFlag);

BoolExprNodeStack idxConjuncts;
const auto conjunctCount = optimizer->decomposeBoolean(idx.idx_condition, idxConjuncts);
const auto conjunctCount = optimizer->decomposeBoolean(idx.idx_condition, idxConjuncts, true);
fb_assert(conjunctCount);

idx.idx_fraction = MAXIMUM_SELECTIVITY;
Expand Down
Loading