8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 08:03:04 +01:00

Fixed CORE-1971: Set the fixed and documented check order for WHERE clause and other conditional sentences.

The order of evaluation is now always from left to right.
This commit is contained in:
dimitr 2009-07-12 10:16:15 +00:00
parent 1c48e5a28f
commit 9b90f012ca
2 changed files with 38 additions and 31 deletions

View File

@ -618,11 +618,12 @@ RecordSource* OPT_compile(thread_db* tdbb,
// around for the rest of the optimization process.
// Set base-point before the parent/distributed nodes begin.
opt->opt_base_conjuncts = (SSHORT) conjunct_count;
const USHORT base_count = (USHORT) conjunct_count;
opt->opt_base_conjuncts = base_count;
// AB: Add parent conjunctions to conjunct_stack, keep in mind
// the outer-streams! For outer streams put missing (IS NULL)
// conjunctions in the missingStack.
// conjunctions in the missing_stack.
//
// opt_rpt[0..opt_base_conjuncts-1] = defined conjunctions to this stream
// opt_rpt[0..opt_base_parent_conjuncts-1] = defined conjunctions to this
@ -633,39 +634,44 @@ RecordSource* OPT_compile(thread_db* tdbb,
//
// allowed = booleans that can never evaluate to NULL/Unknown or turn
// NULL/Unknown into a True or False.
SLONG distributed_count = 0;
NodeStack missingStack;
if (parent_stack && parent_stack->getCount())
USHORT parent_count = 0, distributed_count = 0;
NodeStack missing_stack;
if (parent_stack)
{
NodeStack::iterator iter(*parent_stack);
for (; iter.hasData() && conjunct_count < MAX_CONJUNCTS; ++iter)
for (NodeStack::iterator iter(*parent_stack);
iter.hasData() && conjunct_count < MAX_CONJUNCTS; ++iter)
{
jrd_nod* node = iter.object();
jrd_nod* const node = iter.object();
if ((rse->rse_jointype != blr_inner) && expression_possible_unknown(node))
{
// parent missing conjunctions shouldn't be
// distributed to FULL OUTER JOIN streams at all
if (rse->rse_jointype != blr_full)
{
missingStack.push(node);
missing_stack.push(node);
}
}
else
{
conjunct_stack.push(node);
conjunct_count++;
parent_count++;
}
}
// We've now merged parent, try again to make more conjunctions.
distributed_count = distribute_equalities(conjunct_stack, csb, conjunct_count);
conjunct_count += distributed_count;
}
// The newly created conjunctions belong to the base conjunctions.
// After them are starting the parent conjunctions.
opt->opt_base_parent_conjuncts = opt->opt_base_conjuncts + (SSHORT) distributed_count;
opt->opt_base_parent_conjuncts = opt->opt_base_conjuncts + distributed_count;
// Set base-point before the parent IS NULL nodes begin
opt->opt_base_missing_conjuncts = (SSHORT) conjunct_count;
opt->opt_base_missing_conjuncts = (USHORT) conjunct_count;
// Check if size of optimizer block exceeded.
if (conjunct_count > MAX_CONJUNCTS)
@ -677,41 +683,42 @@ RecordSource* OPT_compile(thread_db* tdbb,
// Put conjunctions in opt structure.
// Note that it's a stack and we get the nodes in reversed order from the stack.
opt->opt_conjuncts.grow(conjunct_count);
SSHORT j = 0;
SSHORT nodeBase = 0;
for (SLONG i = conjunct_count; i > 0; i--)
SSHORT nodeBase = -1, j = -1;
for (SLONG i = conjunct_count; i > 0; i--, j--)
{
jrd_nod* node = conjunct_stack.pop();
jrd_nod* const node = conjunct_stack.pop();
if (i == opt->opt_base_conjuncts)
if (i == base_count)
{
// The base conjunctions
j = 0;
j = base_count - 1;
nodeBase = 0;
}
else if (i == conjunct_count)
{
// The new conjunctions created by "distribution" from the stack
j = 0;
nodeBase = opt->opt_base_conjuncts;
}
else if (i == (conjunct_count - distributed_count))
{
// The parent conjunctions
j = 0;
nodeBase = opt->opt_base_conjuncts + distributed_count;
j = parent_count - 1;
nodeBase = opt->opt_base_parent_conjuncts;
}
else if (i == conjunct_count)
{
// The new conjunctions created by "distribution" from the stack
j = distributed_count - 1;
nodeBase = opt->opt_base_conjuncts;
}
fb_assert(nodeBase >= 0 && j >= 0);
opt->opt_conjuncts[nodeBase + j].opt_conjunct_node = node;
compute_dependencies(node, opt->opt_conjuncts[nodeBase + j].opt_dependencies);
j++;
}
// Put the parent missing nodes on the stack
while (missingStack.hasData() && conjunct_count < MAX_CONJUNCTS)
for (NodeStack::iterator iter(missing_stack);
iter.hasData() && conjunct_count < MAX_CONJUNCTS; ++iter)
{
jrd_nod* const node = iter.object();
opt->opt_conjuncts.grow(conjunct_count + 1);
jrd_nod* node = missingStack.pop();
opt->opt_conjuncts[conjunct_count].opt_conjunct_node = node;
compute_dependencies(node, opt->opt_conjuncts[conjunct_count].opt_dependencies);
conjunct_count++;

View File

@ -392,10 +392,10 @@ public:
CompilerScratch* opt_csb; // compiler scratch block
SLONG opt_combinations; // number of partial orders considered
double opt_best_cost; // cost of best join order
SSHORT opt_base_conjuncts; // number of conjuncts in our rse, next conjuncts are distributed parent
SSHORT opt_base_parent_conjuncts; // number of conjuncts in our rse + distributed with parent, next are parent
SSHORT opt_base_missing_conjuncts; // number of conjuncts in our and parent rse, but without missing
USHORT opt_best_count; // longest length of indexable streams
USHORT opt_base_conjuncts; // number of conjuncts in our rse, next conjuncts are distributed parent
USHORT opt_base_parent_conjuncts; // number of conjuncts in our rse + distributed with parent, next are parent
USHORT opt_base_missing_conjuncts; // number of conjuncts in our and parent rse, but without missing
//USHORT opt_g_flags; // global flags
// 01 Oct 2003. Nickolay Samofatov: this static array takes as much as 256 bytes.
// This is nothing compared to original Firebird 1.5 OptimizerBlk structure size of ~180k