| 590 | // |
| 591 | |
| 592 | Optimizer::Optimizer(thread_db* aTdbb, CompilerScratch* aCsb, RseNode* aRse, bool parentFirstRows) |
| 593 | : PermanentStorage(*aTdbb->getDefaultPool()), |
| 594 | tdbb(aTdbb), csb(aCsb), rse(aRse), |
| 595 | firstRows(rse->firstRows.orElse(parentFirstRows)), |
| 596 | compileStreams(getPool()), |
| 597 | bedStreams(getPool()), |
| 598 | keyStreams(getPool()), |
| 599 | outerStreams(getPool()), |
| 600 | conjuncts(getPool()) |
| 601 | { |
| 602 | // Ignore optimization for first rows in impossible cases |
| 603 | if (firstRows) |
| 604 | { |
| 605 | // Projection is currently always performed using an external sort, |
| 606 | // so all underlying records will be fetched anyway |
| 607 | if (rse->rse_projection) |
| 608 | firstRows = false; |
| 609 | // Aggregation without GROUP BY will also cause all records to be fetched. |
| 610 | // Exception is when MIN/MAX functions could be mapped to an index, |
| 611 | // but this is handled separately inside AggregateSourceNode::compile(). |
| 612 | else if (rse->rse_relations.getCount() == 1) |
| 613 | { |
| 614 | const auto subRse = rse->rse_relations[0]; |
| 615 | const auto aggregate = nodeAs<AggregateSourceNode>(subRse); |
| 616 | if (aggregate && !aggregate->group) |
| 617 | firstRows = false; |
| 618 | } |
| 619 | } |
| 620 | } |
| 621 | |
| 622 | |
| 623 | Optimizer::Optimizer(thread_db* aTdbb, CompilerScratch* aCsb, RseNode* aRse, |
nothing calls this directly
no test coverage detected