test_class.file: oak-core/src/test/java/org/apache/jackrabbit/oak/query/index/TraversingIndexTest.java
test_class.identifier: TraversingIndexTest
test_case.body: @Test
      public void testFacets() {
          TraversingIndex traversingIndex = new TraversingIndex();
          Filter mockFilter = mock(Filter.class);
          when(mockFilter.getPropertyRestriction(REP_FACET)).thenReturn(mock(Filter.PropertyRestriction.class));
          Assert.assertEquals(traversingIndex.getCost(mockFilter, null), Double.POSITIVE_INFINITY, 0.001);
      }
test_case.class_method_signature: TraversingIndexTest.testFacets()
test_case.full_signature: @Test public void testFacets()
test_case.identifier: testFacets
test_case.invocations: mock thenReturn when getPropertyRestriction mock assertEquals getCost
test_case.modifiers: @Test public
test_case.parameters: ()
test_case.return: void
test_case.signature: void testFacets()
focal_class.file: oak-core/src/main/java/org/apache/jackrabbit/oak/query/index/TraversingIndex.java
focal_class.identifier: TraversingIndex
focal_class.interfaces: implements QueryIndex
focal_class.class_method_signature: TraversingIndex.getMinimumCost()
focal_class.full_signature: @Override public double getMinimumCost()
focal_class.identifier: getMinimumCost
focal_class.modifiers: @Override public
focal_class.parameters: ()
focal_class.return: double
focal_class.signature: double getMinimumCost()
focal_class.class_method_signature: TraversingIndex.query(Filter filter, NodeState rootState)
focal_class.full_signature: @Override public Cursor query(Filter filter, NodeState rootState)
focal_class.identifier: query
focal_class.modifiers: @Override public
focal_class.parameters: (Filter filter, NodeState rootState)
focal_class.return: Cursor
focal_class.signature: Cursor query(Filter filter, NodeState rootState)
focal_class.class_method_signature: TraversingIndex.isPotentiallySlow(Filter filter, NodeState rootState)
focal_class.full_signature: public boolean isPotentiallySlow(Filter filter, NodeState rootState)
focal_class.identifier: isPotentiallySlow
focal_class.modifiers: public
focal_class.parameters: (Filter filter, NodeState rootState)
focal_class.return: boolean
focal_class.signature: boolean isPotentiallySlow(Filter filter, NodeState rootState)
focal_class.class_method_signature: TraversingIndex.getCost(Filter filter, NodeState rootState)
focal_class.full_signature: @Override public double getCost(Filter filter, NodeState rootState)
focal_class.identifier: getCost
focal_class.modifiers: @Override public
focal_class.parameters: (Filter filter, NodeState rootState)
focal_class.return: double
focal_class.signature: double getCost(Filter filter, NodeState rootState)
focal_class.class_method_signature: TraversingIndex.getPlan(Filter filter, NodeState rootState)
focal_class.full_signature: @Override public String getPlan(Filter filter, NodeState rootState)
focal_class.identifier: getPlan
focal_class.modifiers: @Override public
focal_class.parameters: (Filter filter, NodeState rootState)
focal_class.return: String
focal_class.signature: String getPlan(Filter filter, NodeState rootState)
focal_class.class_method_signature: TraversingIndex.getIndexName()
focal_class.full_signature: @Override public String getIndexName()
focal_class.identifier: getIndexName
focal_class.modifiers: @Override public
focal_class.parameters: ()
focal_class.return: String
focal_class.signature: String getIndexName()
focal_method.body: @Override
      public double getCost(Filter filter, NodeState rootState) {
          if (filter.getFullTextConstraint() != null) {
              // not an appropriate index for full-text search
              return Double.POSITIVE_INFINITY;
          }
          if (filter.containsNativeConstraint()) {
              // not an appropriate index for native search
              return Double.POSITIVE_INFINITY;
          }
          Filter.PropertyRestriction facetRestriction = filter.getPropertyRestriction(REP_FACET);
          if (facetRestriction != null) {
              // not an appropriate index for facets
              return Double.POSITIVE_INFINITY;
          }
          if (filter.isAlwaysFalse()) {
              return 0;
          }
          // if the path is from a join, then the depth is not correct
          // (the path might be the root node), but that's OK
          String path = filter.getPath();
          PathRestriction restriction = filter.getPathRestriction();
          // the simple cases
          switch (restriction) {
          case EXACT:
              return 1;
          case PARENT:
              if (PathUtils.denotesRoot(path)) {
                  return 0;
              }
              return 1;
          case NO_RESTRICTION:
          case ALL_CHILDREN:
          case DIRECT_CHILDREN:
              break;
          default:
              throw new IllegalArgumentException("Unknown restriction: " + restriction);
          }
          
          if (!path.startsWith(JoinConditionImpl.SPECIAL_PATH_PREFIX)) {
              String testPath = path;
              if (restriction == PathRestriction.NO_RESTRICTION) {
                  testPath = "/";
              }
              long count = NodeCounter.getEstimatedNodeCount(rootState, testPath, true);
              if (count >= 0) {
                  if (restriction == PathRestriction.DIRECT_CHILDREN) {
                      count = count / 2;
                  }
                  return count;
              }
          }
          
          // worst case 100 million descendant nodes
          double nodeCount = 100000000;
          // worst case 100 thousand children
          double nodeCountChildren = 100000;
          switch (restriction) {
          case NO_RESTRICTION:
              break;
          case ALL_CHILDREN:
              if (!PathUtils.denotesRoot(path)) {
                  int depth = PathUtils.getDepth(path);
                  for (int i = depth; i > 0; i--) {
                      // estimate 10 child nodes per node,
                      // but higher than the cost for DIRECT_CHILDREN
                      // (about 100'000)
                      // in any case, the higher the depth of the path,
                      // the lower the cost
                      nodeCount = Math.max(nodeCountChildren * 2 - depth, nodeCount / 10);
                  }
              }
              break;
          case DIRECT_CHILDREN:
              // estimate 100'000 children for now, 
              // to ensure an index is used if there is one
              // TODO we need to have better estimates, see also OAK-1898
               nodeCount = nodeCountChildren;
              break;
          default:
              throw new IllegalArgumentException("Unknown restriction: " + restriction);
          }        
          return nodeCount;
      }
focal_method.class_method_signature: TraversingIndex.getCost(Filter filter, NodeState rootState)
focal_method.full_signature: @Override public double getCost(Filter filter, NodeState rootState)
focal_method.identifier: getCost
focal_method.invocations: getFullTextConstraint containsNativeConstraint getPropertyRestriction isAlwaysFalse getPath getPathRestriction denotesRoot startsWith getEstimatedNodeCount denotesRoot getDepth max
focal_method.modifiers: @Override public
focal_method.parameters: (Filter filter, NodeState rootState)
focal_method.return: double
focal_method.signature: double getCost(Filter filter, NodeState rootState)