| 496 | // |
| 497 | |
| 498 | River* InnerJoin::formRiver() |
| 499 | { |
| 500 | fb_assert(bestCount); |
| 501 | fb_assert(bestStreams.getCount() == bestCount); |
| 502 | |
| 503 | const auto orgSortPtr = sortPtr; |
| 504 | const auto orgSortNode = sortPtr ? *sortPtr : nullptr; |
| 505 | |
| 506 | if (bestCount != innerStreams.getCount()) |
| 507 | sortPtr = nullptr; |
| 508 | |
| 509 | RecordSource* rsb; |
| 510 | StreamList streams; |
| 511 | HalfStaticArray<RecordSource*, OPT_STATIC_ITEMS> rsbs; |
| 512 | HalfStaticArray<BoolExprNode*, OPT_STATIC_ITEMS> equiMatches; |
| 513 | |
| 514 | for (const auto& stream : bestStreams) |
| 515 | { |
| 516 | const bool sortUtilized = (orgSortNode && !*orgSortPtr); |
| 517 | |
| 518 | // We use hash join instead of nested loop join if: |
| 519 | // - stream has equivalence relationship(s) with the prior streams |
| 520 | // (and hashing was estimated to be cheaper) |
| 521 | // AND |
| 522 | // - optimization for first rows is not requested |
| 523 | // OR |
| 524 | // - existing sort was not utilized using an index |
| 525 | |
| 526 | if (rsbs.hasData() && // this is not the first stream |
| 527 | stream.equiMatches.hasData() && |
| 528 | (!optimizer->favorFirstRows() || !sortUtilized)) |
| 529 | { |
| 530 | fb_assert(streams.hasData()); |
| 531 | |
| 532 | // Deactivate priorly joined streams |
| 533 | StreamStateHolder stateHolder(csb, streams); |
| 534 | stateHolder.deactivate(); |
| 535 | |
| 536 | // Create an independent retrieval |
| 537 | rsb = optimizer->generateRetrieval(stream.number, sortPtr, false, false); |
| 538 | |
| 539 | // Create a nested loop join from the priorly processed streams |
| 540 | const auto priorRsb = (rsbs.getCount() == 1) ? rsbs[0] : |
| 541 | FB_NEW_POOL(getPool()) NestedLoopJoin(csb, rsbs.getCount(), rsbs.begin()); |
| 542 | |
| 543 | // Prepare record sources and corresponding equivalence keys for hash-joining |
| 544 | RecordSource* hashJoinRsbs[] = {priorRsb, rsb}; |
| 545 | |
| 546 | HalfStaticArray<NestValueArray*, OPT_STATIC_ITEMS> keys; |
| 547 | |
| 548 | keys.add(FB_NEW_POOL(getPool()) NestValueArray(getPool())); |
| 549 | keys.add(FB_NEW_POOL(getPool()) NestValueArray(getPool())); |
| 550 | |
| 551 | for (const auto match : stream.equiMatches) |
| 552 | { |
| 553 | NestConst<ValueExprNode> node1; |
| 554 | NestConst<ValueExprNode> node2; |
| 555 |
no test coverage detected