| 391 | } |
| 392 | |
| 393 | void Retrieval::analyzeNavigation(const InversionCandidateList& inversions) |
| 394 | { |
| 395 | fb_assert(sort); |
| 396 | |
| 397 | HalfStaticArray<InversionCandidate*, OPT_STATIC_ITEMS> tempCandidates; |
| 398 | InversionCandidate* bestCandidate = nullptr; |
| 399 | |
| 400 | for (auto& indexScratch : indexScratches) |
| 401 | { |
| 402 | auto idx = indexScratch.index; |
| 403 | |
| 404 | // if the number of fields in the sort is greater than the number of |
| 405 | // fields in the index, the index will not be used to optimize the |
| 406 | // sort--note that in the case where the first field is unique, this |
| 407 | // could be optimized, since the sort will be performed correctly by |
| 408 | // navigating on a unique index on the first field--deej |
| 409 | if (sort->expressions.getCount() > idx->idx_count) |
| 410 | continue; |
| 411 | |
| 412 | // if the user-specified access plan for this request didn't |
| 413 | // mention this index, forget it |
| 414 | if ((idx->idx_runtime_flags & idx_plan_dont_use) && |
| 415 | !(idx->idx_runtime_flags & idx_plan_navigate)) |
| 416 | { |
| 417 | continue; |
| 418 | } |
| 419 | |
| 420 | // only a single-column ORDER BY clause can be mapped to |
| 421 | // an expression index |
| 422 | if (idx->idx_flags & idx_expression) |
| 423 | { |
| 424 | if (sort->expressions.getCount() != 1) |
| 425 | continue; |
| 426 | } |
| 427 | |
| 428 | // check to see if the fields in the sort match the fields in the index |
| 429 | // in the exact same order |
| 430 | |
| 431 | unsigned equalSegments = 0; |
| 432 | for (unsigned i = 0; i < MIN(indexScratch.lowerCount, indexScratch.upperCount); i++) |
| 433 | { |
| 434 | const auto& segment = indexScratch.segments[i]; |
| 435 | |
| 436 | if (segment.scanType == segmentScanEqual || |
| 437 | segment.scanType == segmentScanEquivalent || |
| 438 | segment.scanType == segmentScanMissing) |
| 439 | { |
| 440 | equalSegments++; |
| 441 | } |
| 442 | } |
| 443 | |
| 444 | bool usableIndex = true; |
| 445 | const index_desc::idx_repeat* idx_tail = idx->idx_rpt; |
| 446 | const index_desc::idx_repeat* const idx_end = idx_tail + idx->idx_count; |
| 447 | NestConst<ValueExprNode>* ptr = sort->expressions.begin(); |
| 448 | const SortDirection* direction = sort->direction.begin(); |
| 449 | const NullsPlacement* nullOrder = sort->nullOrder.begin(); |
| 450 |
nothing calls this directly
no test coverage detected