Computes the result size via database statistics. @param rt root at compile time (can be null) @param data data reference @return number of results (or -1)
(final Expr rt, final Data data)
| 529 | * @return number of results (or {@code -1}) |
| 530 | */ |
| 531 | private long size(final Expr rt, final Data data) { |
| 532 | // check if path will yield any results |
| 533 | if(root != null && root.size() == 0) return 0; |
| 534 | for(final Expr step : steps) { |
| 535 | if(step.size() == 0) return 0; |
| 536 | } |
| 537 | |
| 538 | // skip computation if: |
| 539 | // - path does not start with document nodes, |
| 540 | // - no database instance is available, outdated, or |
| 541 | // - if context does not contain all database nodes |
| 542 | if(rt == null || !rt.seqType().type.instanceOf(NodeType.DOCUMENT) || |
| 543 | data == null || !data.meta.uptodate || data.meta.ndocs != rt.size()) return -1; |
| 544 | |
| 545 | ArrayList<PathNode> nodes = data.paths.root(); |
| 546 | long lastSize = 1; |
| 547 | final int sl = steps.length; |
| 548 | for(int s = 0; s < sl; s++) { |
| 549 | final Step curr = axisStep(s); |
| 550 | if(curr != null) { |
| 551 | nodes = curr.nodes(nodes, true); |
| 552 | if(nodes == null) return -1; |
| 553 | } else if(s + 1 == sl) { |
| 554 | lastSize = steps[s].size(); |
| 555 | if(lastSize == -1) return -1; |
| 556 | } else { |
| 557 | // stop if a non-axis step is not placed last |
| 558 | return -1; |
| 559 | } |
| 560 | } |
| 561 | |
| 562 | long size = 0; |
| 563 | for(final PathNode pn : nodes) size += pn.stats.count; |
| 564 | return size * lastSize; |
| 565 | } |
| 566 | |
| 567 | /** |
| 568 | * Returns all summary path nodes for the specified location step. |