CollectionQueryEngine implements QueryEngineInternal<O> { @Override public ResultSet<O> retrieve(final Query<O> query, final QueryOptions queryOptions) { @SuppressWarnings("unchecked") OrderByOption<O> orderByOption = (OrderByOption<O>) queryOptions.get(OrderByOption.class); queryOptions.put(ROOT_QUERY, query); final QueryLog queryLog = queryOptions.get(QueryLog.class); SortedKeyStatisticsAttributeIndex<?, O> indexForOrdering = null; if (orderByOption != null) { Double selectivityThreshold = Thresholds.getThreshold(queryOptions, EngineThresholds.INDEX_ORDERING_SELECTIVITY); if (selectivityThreshold == null) { selectivityThreshold = EngineThresholds.INDEX_ORDERING_SELECTIVITY.getThresholdDefault(); } final List<AttributeOrder<O>> allSortOrders = orderByOption.getAttributeOrders(); if (selectivityThreshold != 0.0) { AttributeOrder<O> firstOrder = allSortOrders.iterator().next(); @SuppressWarnings("unchecked") Attribute<O, Comparable> firstAttribute = (Attribute<O, Comparable>)firstOrder.getAttribute(); if (firstAttribute instanceof OrderControlAttribute) { @SuppressWarnings("unchecked") Attribute<O, Comparable> firstAttributeDelegate = ((OrderControlAttribute)firstAttribute).getDelegateAttribute(); firstAttribute = firstAttributeDelegate; } if (firstAttribute instanceof SimpleAttribute || standingQueryIndexes.get(not(has(firstAttribute))) != null) { for (Index<O> index : this.getIndexesOnAttribute(firstAttribute)) { if (index instanceof SortedKeyStatisticsAttributeIndex && !index.isQuantized()) { indexForOrdering = (SortedKeyStatisticsAttributeIndex<?, O>)index; break; } } } if (queryLog != null) { queryLog.log("indexForOrdering: " + (indexForOrdering == null ? null : indexForOrdering.getClass().getSimpleName())); } if (indexForOrdering != null) { final double querySelectivity; if (selectivityThreshold == 1.0) { querySelectivity = 0.0; } else if (!indexForOrdering.supportsQuery(has(firstAttribute), queryOptions)) { querySelectivity = 1.0; } else { final int queryCardinality = retrieveRecursive(query, queryOptions).getMergeCost(); final int indexCardinality = indexForOrdering.retrieve(has(firstAttribute), queryOptions).getMergeCost(); if (queryLog != null) { queryLog.log("queryCardinality: " + queryCardinality); queryLog.log("indexCardinality: " + indexCardinality); } if (indexCardinality == 0) { querySelectivity = 1.0; } else if (queryCardinality > indexCardinality) { querySelectivity = 0.0; } else { querySelectivity = 1.0 - queryCardinality / (double)indexCardinality; } } if (queryLog != null) { queryLog.log("querySelectivity: " + querySelectivity); queryLog.log("selectivityThreshold: " + selectivityThreshold); } if (querySelectivity > selectivityThreshold) { indexForOrdering = null; } } } } ResultSet<O> resultSet; if (indexForOrdering != null) { resultSet = retrieveWithIndexOrdering(query, queryOptions, orderByOption, indexForOrdering); if (queryLog != null) { queryLog.log("orderingStrategy: index"); } } else { resultSet = retrieveWithoutIndexOrdering(query, queryOptions, orderByOption); if (queryLog != null) { queryLog.log("orderingStrategy: materialize"); } } return new CloseableResultSet<O>(resultSet, query, queryOptions) { @Override public void close() { super.close(); CloseableRequestResources.closeForQueryOptions(queryOptions); } }; } CollectionQueryEngine(); @Override void init(final ObjectStore<O> objectStore, final QueryOptions queryOptions); @Override void destroy(QueryOptions queryOptions); @Override void addIndex(Index<O> index, QueryOptions queryOptions); @Override void removeIndex(Index<O> index, QueryOptions queryOptions); @Override Iterable<Index<O>> getIndexes(); @Override ResultSet<O> retrieve(final Query<O> query, final QueryOptions queryOptions); @Override boolean addAll(final ObjectSet<O> objectSet, final QueryOptions queryOptions); @Override boolean removeAll(final ObjectSet<O> objectSet, final QueryOptions queryOptions); @Override void clear(final QueryOptions queryOptions); @Override boolean isMutable(); static final String ROOT_QUERY; }
@Test @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection", "StatementWithEmptyBody"}) public void testOrQueryCollectionScan() { IterationCountingSet<Car> iterationCountingSet = new IterationCountingSet<Car>(CarFactory.createCollectionOfCars(10)); IndexedCollection<Car> collection = new ConcurrentIndexedCollection<Car>(WrappingPersistence.aroundCollection(iterationCountingSet)); Query<Car> query = or(equal(Car.COLOR, Car.Color.BLUE), equal(Car.MANUFACTURER, "Honda")); ResultSet<Car> resultSet = collection.retrieve(query); for (Car car : resultSet) { } Assert.assertEquals(iterationCountingSet.size(), iterationCountingSet.getItemsIteratedCount()); }