Search in sources :

Example 6 with ExecuteProperties

use of com.apple.foundationdb.record.ExecuteProperties in project fdb-record-layer by FoundationDB.

the class IndexingByRecords method buildEndpoints.

@Nonnull
private CompletableFuture<TupleRange> buildEndpoints(@Nonnull FDBRecordStore store, @Nonnull RangeSet rangeSet, @Nullable AtomicLong recordsScanned) {
    boolean isIdempotent = store.getIndexMaintainer(common.getIndex()).isIdempotent();
    final IsolationLevel isolationLevel = isIdempotent ? // before this method's query) will be re-indexed.
    IsolationLevel.SNAPSHOT : IsolationLevel.SERIALIZABLE;
    final ExecuteProperties limit1 = ExecuteProperties.newBuilder().setReturnedRowLimit(1).setIsolationLevel(isolationLevel).build();
    final ScanProperties forward = new ScanProperties(limit1);
    RecordCursor<FDBStoredRecord<Message>> beginCursor = store.scanRecords(recordsRange, null, forward);
    CompletableFuture<Tuple> begin = beginCursor.onNext().thenCompose(result -> {
        if (result.hasNext()) {
            Tuple firstTuple = result.get().getPrimaryKey();
            return buildRange(store, null, firstTuple, recordsScanned).thenApply(vignore -> firstTuple);
        } else {
            // Empty range -- add the whole thing.
            return rangeSet.insertRange(store.ensureContextActive(), null, null).thenApply(bignore -> null);
        }
    });
    final ScanProperties backward = new ScanProperties(limit1, true);
    RecordCursor<FDBStoredRecord<Message>> endCursor = store.scanRecords(recordsRange, null, backward);
    CompletableFuture<Tuple> end = endCursor.onNext().thenCompose(result -> {
        if (result.hasNext()) {
            Tuple lastTuple = result.get().getPrimaryKey();
            return buildRange(store, lastTuple, null, recordsScanned).thenApply(vignore -> lastTuple);
        } else {
            // by the above future, so this has nothing to do.
            return CompletableFuture.completedFuture(null);
        }
    });
    return begin.thenCombine(end, (firstTuple, lastTuple) -> {
        if (firstTuple == null || firstTuple.equals(lastTuple)) {
            return null;
        } else {
            return new TupleRange(firstTuple, lastTuple, EndpointType.RANGE_INCLUSIVE, EndpointType.RANGE_EXCLUSIVE);
        }
    });
}
Also used : ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) IsolationLevel(com.apple.foundationdb.record.IsolationLevel) ScanProperties(com.apple.foundationdb.record.ScanProperties) TupleRange(com.apple.foundationdb.record.TupleRange) Tuple(com.apple.foundationdb.tuple.Tuple) Nonnull(javax.annotation.Nonnull)

Example 7 with ExecuteProperties

use of com.apple.foundationdb.record.ExecuteProperties in project fdb-record-layer by FoundationDB.

the class TextIndexTest method performQueryWithIndexScan.

@Nonnull
private Set<Long> performQueryWithIndexScan(@Nonnull RecordMetaDataHook hook, @Nonnull Index index, @Nonnull QueryComponent filter) throws Exception {
    final ExecuteProperties executeProperties = ExecuteProperties.newBuilder().setTimeLimit(3000).build();
    final RecordQuery query = RecordQuery.newBuilder().setRecordType(SIMPLE_DOC).setRequiredResults(Collections.singletonList(field("doc_id"))).setFilter(filter).build();
    Set<Long> results = new HashSet<>();
    RecordQueryPlan plan;
    byte[] continuation;
    try (FDBRecordContext context = openContext()) {
        openRecordStore(context, hook);
        RecordQueryPlanner planner = new RecordQueryPlanner(recordStore.getRecordMetaData(), recordStore.getRecordStoreState());
        plan = planner.plan(query);
        assertThat(filter, instanceOf(FieldWithComparison.class));
        FieldWithComparison fieldFilter = (FieldWithComparison) filter;
        if (fieldFilter.getComparison() instanceof Comparisons.TextContainsAllPrefixesComparison && ((Comparisons.TextContainsAllPrefixesComparison) fieldFilter.getComparison()).isStrict()) {
            // Strict field field comparisons cannot be covering
            assertThat(plan, descendant(textIndexScan(indexName(index.getName()))));
        } else {
            assertThat(plan, descendant(coveringIndexScan(textIndexScan(indexName(index.getName())))));
        }
        try (RecordCursor<Long> cursor = recordStore.executeQuery(plan, null, executeProperties).map(record -> record.getPrimaryKey().getLong(0))) {
            cursor.forEach(results::add).get();
            continuation = cursor.getNext().getContinuation().toBytes();
        }
    }
    while (continuation != null) {
        try (FDBRecordContext context = openContext()) {
            openRecordStore(context, hook);
            try (RecordCursor<Long> cursor = recordStore.executeQuery(plan, continuation, executeProperties).map(record -> record.getPrimaryKey().getLong(0))) {
                cursor.forEach(results::add).get();
                continuation = cursor.getNext().getContinuation().toBytes();
            }
        }
    }
    return results;
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) FieldWithComparison(com.apple.foundationdb.record.query.expressions.FieldWithComparison) RecordQueryPlanner(com.apple.foundationdb.record.query.plan.RecordQueryPlanner) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) HashSet(java.util.HashSet) Nonnull(javax.annotation.Nonnull)

Example 8 with ExecuteProperties

use of com.apple.foundationdb.record.ExecuteProperties in project fdb-record-layer by FoundationDB.

the class TextIndexTest method queryDocumentsWithScanLimit.

@Test
public void queryDocumentsWithScanLimit() throws Exception {
    // Load a big (ish) data set
    final int recordCount = 100;
    final int batchSize = 10;
    for (int i = 0; i < recordCount; i += batchSize) {
        try (FDBRecordContext context = openContext()) {
            openRecordStore(context);
            for (int j = 0; j < batchSize; j++) {
                SimpleDocument document = SimpleDocument.newBuilder().setDocId(i + j).setText((i + j) % 2 == 0 ? "some" : "text").build();
                recordStore.saveRecord(document);
            }
            commit(context);
        }
    }
    try (FDBRecordContext context = openContext()) {
        openRecordStore(context);
        RecordQuery query = RecordQuery.newBuilder().setRecordType(SIMPLE_DOC).setFilter(Query.field("text").text().containsAll("some text")).build();
        RecordQueryPlan plan = planner.plan(query);
        boolean done = false;
        int totalKeysLoaded = 0;
        byte[] continuation = null;
        while (!done) {
            final int priorKeysLoaded = getLoadTextEntryCount(recordStore);
            ExecuteProperties executeProperties = ExecuteProperties.newBuilder().setScannedRecordsLimit(50).build();
            RecordCursor<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan, continuation, executeProperties);
            assertEquals(Collections.emptyList(), cursor.asList().get());
            RecordCursorResult<FDBQueriedRecord<Message>> noNextResult = cursor.getNext();
            assertThat(noNextResult.hasNext(), is(false));
            final int newKeysLoaded = getLoadTextEntryCount(recordStore);
            totalKeysLoaded += newKeysLoaded - priorKeysLoaded;
            if (!noNextResult.getNoNextReason().isSourceExhausted()) {
                assertEquals(50, newKeysLoaded - priorKeysLoaded);
                assertEquals(RecordCursor.NoNextReason.SCAN_LIMIT_REACHED, noNextResult.getNoNextReason());
                assertNotNull(noNextResult.getContinuation().toBytes());
            } else {
                assertNull(noNextResult.getContinuation().toBytes());
                done = true;
            }
            continuation = noNextResult.getContinuation().toBytes();
        }
        assertEquals(recordCount + 2, totalKeysLoaded);
        commit(context);
    }
}
Also used : RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) SimpleDocument(com.apple.foundationdb.record.TestRecordsTextProto.SimpleDocument) RecordQuery(com.apple.foundationdb.record.query.RecordQuery) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) Test(org.junit.jupiter.api.Test)

Example 9 with ExecuteProperties

use of com.apple.foundationdb.record.ExecuteProperties in project fdb-record-layer by FoundationDB.

the class GeophileQueryTest method testDistance.

@Test
@Tag(Tags.Slow)
public void testDistance() throws Exception {
    final RecordMetaDataHook hook = md -> {
        md.addIndex("City", CITY_LOCATION_COVERING_INDEX);
    };
    loadCities(hook, 0);
    final int centerId = 5391959;
    final double distance = 1;
    final int scanLimit = 5000;
    final RecordQueryPlan scanPlan = distanceFilterScan(distance);
    final Set<Integer> scanResults = new HashSet<>();
    byte[] continuation = null;
    do {
        try (FDBRecordContext context = openContext()) {
            openRecordStore(context, hook);
            EvaluationContext joinContext = bindCenter(centerId);
            ExecuteProperties executeProperties = ExecuteProperties.newBuilder().setScannedRecordsLimit(scanLimit).build();
            RecordCursor<FDBQueriedRecord<Message>> recordCursor = scanPlan.execute(recordStore, joinContext, continuation, executeProperties);
            recordCursor.forEach(city -> {
                TestRecordsGeoProto.City.Builder cityBuilder = TestRecordsGeoProto.City.newBuilder().mergeFrom(city.getRecord());
                LOGGER.debug(String.format("Scan found %s: %s", cityBuilder.getGeoNameId(), cityBuilder.getName()));
                scanResults.add(cityBuilder.getGeoNameId());
            }).join();
            continuation = recordCursor.getNext().getContinuation().toBytes();
            commit(context);
        }
    } while (continuation != null);
    final RecordQueryPlan indexPlan = distanceSpatialQuery(distance, false);
    final Set<Integer> indexResults = new HashSet<>();
    try (FDBRecordContext context = openContext()) {
        openRecordStore(context, hook);
        RecordCursor<FDBQueriedRecord<Message>> recordCursor = indexPlan.execute(recordStore, bindCenter(centerId));
        recordCursor.forEach(city -> {
            TestRecordsGeoProto.City.Builder cityBuilder = TestRecordsGeoProto.City.newBuilder().mergeFrom(city.getRecord());
            LOGGER.debug(String.format("Index found %s: %s", cityBuilder.getGeoNameId(), cityBuilder.getName()));
            indexResults.add(cityBuilder.getGeoNameId());
        }).join();
        int given = timer.getCount(FDBStoreTimer.Counts.QUERY_FILTER_GIVEN);
        int passed = timer.getCount(FDBStoreTimer.Counts.QUERY_FILTER_PASSED);
        int discarded = timer.getCount(FDBStoreTimer.Counts.QUERY_DISCARDED);
        assertThat("Should have passed more than discarded", passed, greaterThan(discarded));
        commit(context);
    }
    final RecordQueryPlan coveringPlan = distanceSpatialQuery(distance, true);
    final Set<Integer> coveringResults = new HashSet<>();
    try (FDBRecordContext context = openContext()) {
        openRecordStore(context, hook);
        RecordCursor<FDBQueriedRecord<Message>> recordCursor = indexPlan.execute(recordStore, bindCenter(centerId));
        recordCursor.forEach(city -> {
            TestRecordsGeoProto.City.Builder cityBuilder = TestRecordsGeoProto.City.newBuilder().mergeFrom(city.getRecord());
            LOGGER.debug(String.format("Covering found %s: %s", cityBuilder.getGeoNameId(), cityBuilder.getName()));
            coveringResults.add(cityBuilder.getGeoNameId());
        }).join();
        commit(context);
    }
    assertEquals(scanResults, indexResults);
    assertEquals(scanResults, coveringResults);
}
Also used : RecordQueryFilterPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryFilterPlan) LoggerFactory(org.slf4j.LoggerFactory) Coordinate(org.locationtech.jts.geom.Coordinate) Bindings(com.apple.foundationdb.record.Bindings) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) Tuple(com.apple.foundationdb.tuple.Tuple) Pair(org.apache.commons.lang3.tuple.Pair) Expressions.concatenateFields(com.apple.foundationdb.record.metadata.Key.Expressions.concatenateFields) RecordQueryScanPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryScanPlan) Expressions.concat(com.apple.foundationdb.record.metadata.Key.Expressions.concat) Tag(org.junit.jupiter.api.Tag) Query(com.apple.foundationdb.record.query.expressions.Query) DoubleValueOrParameter(com.apple.foundationdb.record.spatial.common.DoubleValueOrParameter) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) FDBStoreTimer(com.apple.foundationdb.record.provider.foundationdb.FDBStoreTimer) Matchers.allOf(org.hamcrest.Matchers.allOf) Set(java.util.Set) Point(org.locationtech.jts.geom.Point) CompletionException(java.util.concurrent.CompletionException) Expressions.keyWithValue(com.apple.foundationdb.record.metadata.Key.Expressions.keyWithValue) Test(org.junit.jupiter.api.Test) GeoJsonReader(org.locationtech.jts.io.geojson.GeoJsonReader) TopologyException(org.locationtech.jts.geom.TopologyException) ParseException(org.locationtech.jts.io.ParseException) EvaluationContext(com.apple.foundationdb.record.EvaluationContext) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) Matchers.equalTo(org.hamcrest.Matchers.equalTo) Geometry(org.locationtech.jts.geom.Geometry) Expressions.function(com.apple.foundationdb.record.metadata.Key.Expressions.function) Matchers.greaterThan(org.hamcrest.Matchers.greaterThan) RecordQueryTypeFilterPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryTypeFilterPlan) GeoPointWithinDistanceComponent(com.apple.foundationdb.record.spatial.common.GeoPointWithinDistanceComponent) FDBIndexedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBIndexedRecord) FDBRecordStoreQueryTestBase(com.apple.foundationdb.record.provider.foundationdb.query.FDBRecordStoreQueryTestBase) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) HashSet(java.util.HashSet) Matchers.hasProperty(org.hamcrest.Matchers.hasProperty) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Nonnull(javax.annotation.Nonnull) Expressions.field(com.apple.foundationdb.record.metadata.Key.Expressions.field) FDBStoredRecord(com.apple.foundationdb.record.provider.foundationdb.FDBStoredRecord) GeometryFactory(org.locationtech.jts.geom.GeometryFactory) Logger(org.slf4j.Logger) Tags(com.apple.test.Tags) Throwables(com.google.common.base.Throwables) Matchers(org.hamcrest.Matchers) ScanComparisons(com.apple.foundationdb.record.query.plan.ScanComparisons) FileInputStream(java.io.FileInputStream) InputStreamReader(java.io.InputStreamReader) Index(com.apple.foundationdb.record.metadata.Index) Expressions.value(com.apple.foundationdb.record.metadata.Key.Expressions.value) FDBException(com.apple.foundationdb.FDBException) Message(com.google.protobuf.Message) RecordCursor(com.apple.foundationdb.record.RecordCursor) BufferedReader(java.io.BufferedReader) Collections(java.util.Collections) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) Point(org.locationtech.jts.geom.Point) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) FDBQueriedRecord(com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord) FDBRecordContext(com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext) EvaluationContext(com.apple.foundationdb.record.EvaluationContext) HashSet(java.util.HashSet) Test(org.junit.jupiter.api.Test) Tag(org.junit.jupiter.api.Tag)

Example 10 with ExecuteProperties

use of com.apple.foundationdb.record.ExecuteProperties in project fdb-record-layer by FoundationDB.

the class QueryPlanCursorTest method compareSkipsAndCursors.

private void compareSkipsAndCursors(RecordQueryPlan plan, int amount) throws Exception {
    final Function<FDBQueriedRecord<Message>, Long> getRecNo = r -> {
        TestRecords1Proto.MySimpleRecord.Builder record = TestRecords1Proto.MySimpleRecord.newBuilder();
        record.mergeFrom(r.getRecord());
        return record.getRecNo();
    };
    final ExecuteProperties justLimit = ExecuteProperties.newBuilder().setReturnedRowLimit(amount).build();
    try (FDBRecordContext context = openContext()) {
        openSimpleRecordStore(context);
        final List<Long> whole;
        try (RecordCursor<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan)) {
            whole = cursor.map(getRecNo).asList().get();
        }
        assertTrue(whole.size() > amount, "should have more than one batch");
        final List<Long> byCursors = new ArrayList<>();
        byte[] continuation = null;
        do {
            try (RecordCursor<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan, continuation, justLimit)) {
                RecordCursorResult<FDBQueriedRecord<Message>> result = null;
                do {
                    result = cursor.getNext();
                    if (result.hasNext()) {
                        byCursors.add(getRecNo.apply(result.get()));
                    }
                } while (result.hasNext());
                continuation = result.getContinuation().toBytes();
            }
        } while (continuation != null);
        assertEquals(whole, byCursors);
        final List<Long> byOffsets = new ArrayList<>();
        int offset = 0;
        while (true) {
            final ExecuteProperties skipAndLimit = ExecuteProperties.newBuilder().setSkip(offset).setReturnedRowLimit(amount).setIsolationLevel(justLimit.getIsolationLevel()).build();
            try (RecordCursor<FDBQueriedRecord<Message>> cursor = recordStore.executeQuery(plan, null, skipAndLimit)) {
                final List<Long> next = cursor.map(getRecNo).asList().get();
                byOffsets.addAll(next);
                if (next.size() < amount) {
                    break;
                } else {
                    offset += next.size();
                }
            }
        }
        assertEquals(whole, byOffsets);
    }
}
Also used : BeforeEach(org.junit.jupiter.api.BeforeEach) RecordQueryFilterPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryFilterPlan) Arrays(java.util.Arrays) RecordQueryIntersectionPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryIntersectionPlan) LoggerFactory(org.slf4j.LoggerFactory) Bindings(com.apple.foundationdb.record.Bindings) RecordQueryPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan) Function(java.util.function.Function) ArrayList(java.util.ArrayList) Key(com.apple.foundationdb.record.metadata.Key) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties) RecordCursorResult(com.apple.foundationdb.record.RecordCursorResult) RecordQueryScanPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryScanPlan) Tag(org.junit.jupiter.api.Tag) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) RecordQueryUnionPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryUnionPlan) RecordQueryIndexPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryIndexPlan) Query(com.apple.foundationdb.record.query.expressions.Query) KeyExpression(com.apple.foundationdb.record.metadata.expressions.KeyExpression) ImmutableSet(com.google.common.collect.ImmutableSet) Logger(org.slf4j.Logger) TestRecords1Proto(com.apple.foundationdb.record.TestRecords1Proto) Tags(com.apple.test.Tags) Matchers.lessThanOrEqualTo(org.hamcrest.Matchers.lessThanOrEqualTo) ScanComparisons(com.apple.foundationdb.record.query.plan.ScanComparisons) Test(org.junit.jupiter.api.Test) Comparisons(com.apple.foundationdb.record.query.expressions.Comparisons) List(java.util.List) EvaluationContext(com.apple.foundationdb.record.EvaluationContext) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) RecordQueryInValuesJoinPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryInValuesJoinPlan) Message(com.google.protobuf.Message) RecordCursor(com.apple.foundationdb.record.RecordCursor) QueryComponent(com.apple.foundationdb.record.query.expressions.QueryComponent) RecordQueryTypeFilterPlan(com.apple.foundationdb.record.query.plan.plans.RecordQueryTypeFilterPlan) Collections(java.util.Collections) TestRecords1Proto(com.apple.foundationdb.record.TestRecords1Proto) ArrayList(java.util.ArrayList) ExecuteProperties(com.apple.foundationdb.record.ExecuteProperties)

Aggregations

ExecuteProperties (com.apple.foundationdb.record.ExecuteProperties)38 Nonnull (javax.annotation.Nonnull)29 Message (com.google.protobuf.Message)23 RecordCursor (com.apple.foundationdb.record.RecordCursor)20 ScanProperties (com.apple.foundationdb.record.ScanProperties)18 List (java.util.List)17 Index (com.apple.foundationdb.record.metadata.Index)15 FDBQueriedRecord (com.apple.foundationdb.record.provider.foundationdb.FDBQueriedRecord)15 FDBRecordContext (com.apple.foundationdb.record.provider.foundationdb.FDBRecordContext)15 RecordQueryPlan (com.apple.foundationdb.record.query.plan.plans.RecordQueryPlan)15 RecordCursorResult (com.apple.foundationdb.record.RecordCursorResult)14 Function (java.util.function.Function)14 Nullable (javax.annotation.Nullable)13 API (com.apple.foundationdb.annotation.API)12 EvaluationContext (com.apple.foundationdb.record.EvaluationContext)12 Tuple (com.apple.foundationdb.tuple.Tuple)12 IsolationLevel (com.apple.foundationdb.record.IsolationLevel)11 TupleRange (com.apple.foundationdb.record.TupleRange)11 ArrayList (java.util.ArrayList)11 Collections (java.util.Collections)10