mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-24 07:23:03 +01:00
Allowed merge joins for IS NOT DISTINCT equalities.
This commit is contained in:
parent
a70fdf00b7
commit
5f39df8d27
@ -3496,13 +3496,13 @@ static bool gen_sort_merge(thread_db* tdbb, OptimizerBlk* opt, RiverStack& org_r
|
|||||||
jrd_nod **eq_class, **ptr;
|
jrd_nod **eq_class, **ptr;
|
||||||
DEV_BLKCHK(opt, type_opt);
|
DEV_BLKCHK(opt, type_opt);
|
||||||
SET_TDBB(tdbb);
|
SET_TDBB(tdbb);
|
||||||
//Database* dbb = tdbb->getDatabase();
|
|
||||||
|
|
||||||
// Count the number of "rivers" involved in the operation, then allocate
|
// Count the number of "rivers" involved in the operation, then allocate
|
||||||
// a scratch block large enough to hold values to compute equality
|
// a scratch block large enough to hold values to compute equality
|
||||||
// classes.
|
// classes.
|
||||||
USHORT cnt = 0;
|
USHORT cnt = 0;
|
||||||
for (RiverStack::iterator stack1(org_rivers); stack1.hasData(); ++stack1) {
|
for (RiverStack::iterator stack1(org_rivers); stack1.hasData(); ++stack1)
|
||||||
|
{
|
||||||
stack1.object()->riv_number = cnt++;
|
stack1.object()->riv_number = cnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3517,18 +3517,26 @@ static bool gen_sort_merge(thread_db* tdbb, OptimizerBlk* opt, RiverStack& org_r
|
|||||||
const OptimizerBlk::opt_conjunct* const end = tail + opt->opt_base_conjuncts;
|
const OptimizerBlk::opt_conjunct* const end = tail + opt->opt_base_conjuncts;
|
||||||
for (; tail < end; tail++)
|
for (; tail < end; tail++)
|
||||||
{
|
{
|
||||||
if (tail->opt_conjunct_flags & opt_conjunct_used) {
|
if (tail->opt_conjunct_flags & opt_conjunct_used)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
jrd_nod* node = tail->opt_conjunct_node;
|
jrd_nod* node = tail->opt_conjunct_node;
|
||||||
if (node->nod_type != nod_eql) {
|
|
||||||
|
if (node->nod_type != nod_eql &&
|
||||||
|
node->nod_type != nod_equiv)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
jrd_nod* node1 = node->nod_arg[0];
|
jrd_nod* node1 = node->nod_arg[0];
|
||||||
jrd_nod* node2 = node->nod_arg[1];
|
jrd_nod* node2 = node->nod_arg[1];
|
||||||
|
|
||||||
for (RiverStack::iterator stack0(org_rivers); stack0.hasData(); ++stack0)
|
for (RiverStack::iterator stack0(org_rivers); stack0.hasData(); ++stack0)
|
||||||
{
|
{
|
||||||
River* river1 = stack0.object();
|
River* const river1 = stack0.object();
|
||||||
|
|
||||||
if (!river_reference(river1, node1))
|
if (!river_reference(river1, node1))
|
||||||
{
|
{
|
||||||
if (river_reference(river1, node2))
|
if (river_reference(river1, node2))
|
||||||
@ -3537,13 +3545,16 @@ static bool gen_sort_merge(thread_db* tdbb, OptimizerBlk* opt, RiverStack& org_r
|
|||||||
node1 = node2;
|
node1 = node2;
|
||||||
node2 = node;
|
node2 = node;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (RiverStack::iterator stack2(stack0); (++stack2).hasData();)
|
for (RiverStack::iterator stack2(stack0); (++stack2).hasData();)
|
||||||
{
|
{
|
||||||
River* river2 = stack2.object();
|
River* const river2 = stack2.object();
|
||||||
|
|
||||||
if (river_reference(river2, node2))
|
if (river_reference(river2, node2))
|
||||||
{
|
{
|
||||||
for (eq_class = classes; eq_class < last_class; eq_class += cnt)
|
for (eq_class = classes; eq_class < last_class; eq_class += cnt)
|
||||||
@ -3554,9 +3565,12 @@ static bool gen_sort_merge(thread_db* tdbb, OptimizerBlk* opt, RiverStack& org_r
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eq_class[river1->riv_number] = node1;
|
eq_class[river1->riv_number] = node1;
|
||||||
eq_class[river2->riv_number] = node2;
|
eq_class[river2->riv_number] = node2;
|
||||||
if (eq_class == last_class) {
|
|
||||||
|
if (eq_class == last_class)
|
||||||
|
{
|
||||||
last_class += cnt;
|
last_class += cnt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3569,10 +3583,11 @@ static bool gen_sort_merge(thread_db* tdbb, OptimizerBlk* opt, RiverStack& org_r
|
|||||||
// to indicate that nothing could be done.
|
// to indicate that nothing could be done.
|
||||||
|
|
||||||
USHORT river_cnt = 0, stream_cnt = 0;
|
USHORT river_cnt = 0, stream_cnt = 0;
|
||||||
Firebird::HalfStaticArray<jrd_nod**, OPT_STATIC_ITEMS> selected_classes(*tdbb->getDefaultPool(), cnt);
|
Firebird::HalfStaticArray<jrd_nod**, OPT_STATIC_ITEMS> selected_classes(cnt);
|
||||||
for (eq_class = classes; eq_class < last_class; eq_class += cnt)
|
for (eq_class = classes; eq_class < last_class; eq_class += cnt)
|
||||||
{
|
{
|
||||||
i = river_count(cnt, eq_class);
|
i = river_count(cnt, eq_class);
|
||||||
|
|
||||||
if (i > river_cnt)
|
if (i > river_cnt)
|
||||||
{
|
{
|
||||||
river_cnt = i;
|
river_cnt = i;
|
||||||
@ -3583,20 +3598,26 @@ static bool gen_sort_merge(thread_db* tdbb, OptimizerBlk* opt, RiverStack& org_r
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
class_mask(cnt, eq_class, selected_rivers2);
|
class_mask(cnt, eq_class, selected_rivers2);
|
||||||
|
|
||||||
for (i = 0; i < OPT_STREAM_BITS; i++)
|
for (i = 0; i < OPT_STREAM_BITS; i++)
|
||||||
{
|
{
|
||||||
if ((selected_rivers[i] & selected_rivers2[i]) != selected_rivers[i]) {
|
if ((selected_rivers[i] & selected_rivers2[i]) != selected_rivers[i])
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i == OPT_STREAM_BITS) {
|
|
||||||
|
if (i == OPT_STREAM_BITS)
|
||||||
|
{
|
||||||
selected_classes.add(eq_class);
|
selected_classes.add(eq_class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!river_cnt)
|
if (!river_cnt)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
HalfStaticArray<SortedStream*, OPT_STATIC_ITEMS> sorts;
|
HalfStaticArray<SortedStream*, OPT_STATIC_ITEMS> sorts;
|
||||||
HalfStaticArray<jrd_nod*, OPT_STATIC_ITEMS> keys;
|
HalfStaticArray<jrd_nod*, OPT_STATIC_ITEMS> keys;
|
||||||
@ -3608,13 +3629,19 @@ static bool gen_sort_merge(thread_db* tdbb, OptimizerBlk* opt, RiverStack& org_r
|
|||||||
for (RiverStack::iterator stack3(org_rivers); stack3.hasData(); ++stack3)
|
for (RiverStack::iterator stack3(org_rivers); stack3.hasData(); ++stack3)
|
||||||
{
|
{
|
||||||
River* const river1 = stack3.object();
|
River* const river1 = stack3.object();
|
||||||
if (!(TEST_DEP_BIT(selected_rivers, river1->riv_number))) {
|
|
||||||
|
if (!(TEST_DEP_BIT(selected_rivers, river1->riv_number)))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (river1->riv_number > lowestRiverPosition) {
|
|
||||||
|
if (river1->riv_number > lowestRiverPosition)
|
||||||
|
{
|
||||||
lowestRiverPosition = river1->riv_number;
|
lowestRiverPosition = river1->riv_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream_cnt += river1->riv_count;
|
stream_cnt += river1->riv_count;
|
||||||
|
|
||||||
jrd_nod* const sort = FB_NEW_RPT(*tdbb->getDefaultPool(), selected_classes.getCount() * 3) jrd_nod();
|
jrd_nod* const sort = FB_NEW_RPT(*tdbb->getDefaultPool(), selected_classes.getCount() * 3) jrd_nod();
|
||||||
sort->nod_type = nod_sort;
|
sort->nod_type = nod_sort;
|
||||||
sort->nod_count = (USHORT) selected_classes.getCount();
|
sort->nod_count = (USHORT) selected_classes.getCount();
|
||||||
@ -3647,24 +3674,28 @@ static bool gen_sort_merge(thread_db* tdbb, OptimizerBlk* opt, RiverStack& org_r
|
|||||||
RiverStack newRivers(org_rivers.getPool());
|
RiverStack newRivers(org_rivers.getPool());
|
||||||
while (org_rivers.hasData())
|
while (org_rivers.hasData())
|
||||||
{
|
{
|
||||||
River* river2 = org_rivers.pop();
|
River* const river2 = org_rivers.pop();
|
||||||
|
|
||||||
if (TEST_DEP_BIT(selected_rivers, river2->riv_number))
|
if (TEST_DEP_BIT(selected_rivers, river2->riv_number))
|
||||||
{
|
{
|
||||||
memcpy(stream, river2->riv_streams, river2->riv_count);
|
memcpy(stream, river2->riv_streams, river2->riv_count);
|
||||||
stream += river2->riv_count;
|
stream += river2->riv_count;
|
||||||
// If this is the lowest position put in the new river.
|
// If this is the lowest position put in the new river.
|
||||||
if (river2->riv_number == lowestRiverPosition) {
|
if (river2->riv_number == lowestRiverPosition)
|
||||||
|
{
|
||||||
newRivers.push(river1);
|
newRivers.push(river1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
newRivers.push(river2);
|
newRivers.push(river2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AB: Put new rivers list back in the original list.
|
// AB: Put new rivers list back in the original list.
|
||||||
// Note that the rivers in the new stack are reversed.
|
// Note that the rivers in the new stack are reversed.
|
||||||
while (newRivers.hasData()) {
|
while (newRivers.hasData())
|
||||||
|
{
|
||||||
org_rivers.push(newRivers.pop());
|
org_rivers.push(newRivers.pop());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3686,6 +3717,7 @@ static bool gen_sort_merge(thread_db* tdbb, OptimizerBlk* opt, RiverStack& org_r
|
|||||||
for (tail = opt->opt_conjuncts.begin(); tail < end; tail++)
|
for (tail = opt->opt_conjuncts.begin(); tail < end; tail++)
|
||||||
{
|
{
|
||||||
jrd_nod* const node = tail->opt_conjunct_node;
|
jrd_nod* const node = tail->opt_conjunct_node;
|
||||||
|
|
||||||
if (!(tail->opt_conjunct_flags & opt_conjunct_used) &&
|
if (!(tail->opt_conjunct_flags & opt_conjunct_used) &&
|
||||||
OPT_computable(opt->opt_csb, node, -1, false, false))
|
OPT_computable(opt->opt_csb, node, -1, false, false))
|
||||||
{
|
{
|
||||||
@ -4420,14 +4452,6 @@ static bool node_equality(const jrd_nod* node1, const jrd_nod* node2)
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case nod_gtr:
|
|
||||||
case nod_geq:
|
|
||||||
case nod_leq:
|
|
||||||
case nod_lss:
|
|
||||||
case nod_matches:
|
|
||||||
case nod_contains:
|
|
||||||
case nod_like:
|
|
||||||
case nod_similar:
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user